/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "zobjects_gtk.h"

ZlangImportObjectFunction ZlangImportObject_guiwindow;

ZlangImportObjectFunction ZlangImportObject_guifixedlayout;
ZlangImportObjectFunction ZlangImportObject_guiboxlayout;
ZlangImportObjectFunction ZlangImportObject_guicenterboxlayout;
ZlangImportObjectFunction ZlangImportObject_guiflowboxlayout;
ZlangImportObjectFunction ZlangImportObject_guigridlayout;
ZlangImportObjectFunction ZlangImportObject_guiscrollwindowlayout;
ZlangImportObjectFunction ZlangImportObject_guiframelayout;
ZlangImportObjectFunction ZlangImportObject_guipanedlayout;
ZlangImportObjectFunction ZlangImportObject_guinotebooklayout;
ZlangImportObjectFunction ZlangImportObject_guipopoverlayout;

ZlangImportObjectFunction ZlangImportObject_guimenubar;
ZlangImportObjectFunction ZlangImportObject_guimenu;
ZlangImportObjectFunction ZlangImportObject_guimenuitem;

ZlangImportObjectFunction ZlangImportObject_guitoolbar;
ZlangImportObjectFunction ZlangImportObject_guitoolseparatoritem;

ZlangImportObjectFunction ZlangImportObject_guilabel;
ZlangImportObjectFunction ZlangImportObject_guiedit;
ZlangImportObjectFunction ZlangImportObject_guieditarea;
ZlangImportObjectFunction ZlangImportObject_guisourceeditarea;
ZlangImportObjectFunction ZlangImportObject_guibutton;
ZlangImportObjectFunction ZlangImportObject_guispinbutton;
ZlangImportObjectFunction ZlangImportObject_guicheckbutton;
ZlangImportObjectFunction ZlangImportObject_guiradiobutton;
ZlangImportObjectFunction ZlangImportObject_guitogglebutton;
ZlangImportObjectFunction ZlangImportObject_guilinkbutton;
ZlangImportObjectFunction ZlangImportObject_guilistbox;
ZlangImportObjectFunction ZlangImportObject_guicombobox;
ZlangImportObjectFunction ZlangImportObject_guitable;
ZlangImportObjectFunction ZlangImportObject_guitablecolumn_int_text;
ZlangImportObjectFunction ZlangImportObject_guitablecolumn_double_text;
ZlangImportObjectFunction ZlangImportObject_guitablecolumn_string_text;
ZlangImportObjectFunction ZlangImportObject_guitablecolumn_icon;
ZlangImportObjectFunction ZlangImportObject_guitreetable;
ZlangImportObjectFunction ZlangImportObject_guitreenode;
ZlangImportObjectFunction ZlangImportObject_guitreecolumn_toggle;
ZlangImportObjectFunction ZlangImportObject_guitreecolumn_progress;
ZlangImportObjectFunction ZlangImportObject_guitreecolumn_int_text;
ZlangImportObjectFunction ZlangImportObject_guitreecolumn_double_text;
ZlangImportObjectFunction ZlangImportObject_guitreecolumn_string_text;
ZlangImportObjectFunction ZlangImportObject_guilevelbar;
ZlangImportObjectFunction ZlangImportObject_guiprogressbar;
ZlangImportObjectFunction ZlangImportObject_guicalendar;
ZlangImportObjectFunction ZlangImportObject_guiimage;
ZlangImportObjectFunction ZlangImportObject_guiswitch;
ZlangImportObjectFunction ZlangImportObject_guivideo;
ZlangImportObjectFunction ZlangImportObject_guiseparator;
ZlangImportObjectFunction ZlangImportObject_guictl;

ZlangImportObjectFunction ZlangImportObject_guimessagedialog;
ZlangImportObjectFunction ZlangImportObject_guiaboutdialog;
ZlangImportObjectFunction ZlangImportObject_guicolorchooserdialog;
ZlangImportObjectFunction ZlangImportObject_guifilechooserdialog;
ZlangImportObjectFunction ZlangImportObject_guifontchooserdialog;

ZlangImportObjectFunction ZlangImportObject_guiorientation;
ZlangImportObjectFunction ZlangImportObject_guialign;
ZlangImportObjectFunction ZlangImportObject_guijustify;
ZlangImportObjectFunction ZlangImportObject_guimouse;
ZlangImportObjectFunction ZlangImportObject_guikey;
ZlangImportObjectFunction ZlangImportObject_guilicense;

ZlangImportObjectFunction ZlangImportObject_guimonitor;
ZlangImportObjectFunction ZlangImportObject_guiclipboard;

char		_GTKZLANG_VERSION_0_5_9_0[] = "0.5.9.0" ;
char		*_GTKZLANG_VERSION = _GTKZLANG_VERSION_0_5_9_0 ;

int AppendStringList( struct list_head *string_list , char *str )
{
	char			*p = NULL ;
	size_t			str_len ;
	size_t			alloc_len ;
	struct StringListNode	*string_list_node = NULL ;

	str_len = strlen(str) ;
	alloc_len = sizeof(struct list_head) + str_len + 1 ;
	p = malloc( alloc_len ) ;
	if( p == NULL )
		return -1;
	memset( p , 0x00 , alloc_len );

	memcpy( p + sizeof(struct list_head) , str , str_len );
	string_list_node = (struct StringListNode *)p ;

	list_add_tail( & (string_list_node->str_list_node) , string_list );

	return 0;
}

struct StringListNode *TravelStringList( struct list_head *string_list , struct StringListNode *string_list_node )
{
	if( string_list_node == NULL )
		return list_first_entry_or_null( string_list , struct StringListNode , str_list_node );
	else
		return list_next_entry_or_null( string_list_node , string_list , struct StringListNode , str_list_node );
}

void UnlinkStringListNode( struct StringListNode *string_list_node )
{
	list_del( & (string_list_node->str_list_node) );

	free( string_list_node );

	return;
}

void FastDestroyObject( void *obj )
{
	DestroyObject( GetZlangRuntime() , obj );
	return;
}

void SetGtkWidgetMarginWidth( GtkWidget *gtk_widget , int margin_width )
{
	gtk_widget_set_margin_top( gtk_widget , margin_width );
	gtk_widget_set_margin_bottom( gtk_widget , margin_width );
	gtk_widget_set_margin_start( gtk_widget , margin_width );
	gtk_widget_set_margin_end( gtk_widget , margin_width );
	return;;
}

void SetGtkWidgetVerticalMarginWidth( GtkWidget *gtk_widget , int vertical_margin_width )
{
	gtk_widget_set_margin_top( gtk_widget , vertical_margin_width );
	gtk_widget_set_margin_bottom( gtk_widget , vertical_margin_width );
	return;;
}

void SetGtkWidgetHorizontalMarginWidth( GtkWidget *gtk_widget , int horizon_margin_width )
{
	gtk_widget_set_margin_start( gtk_widget , horizon_margin_width );
	gtk_widget_set_margin_end( gtk_widget , horizon_margin_width );
	return;;
}

void SetGtkWidgetMarginAllWidth( GtkWidget *gtk_widget , int top_margin_width , int bottom_margin_width , int left_margin_width , int right_margin_width )
{
	gtk_widget_set_margin_top( gtk_widget , top_margin_width );
	gtk_widget_set_margin_bottom( gtk_widget , bottom_margin_width );
	gtk_widget_set_margin_start( gtk_widget , left_margin_width );
	gtk_widget_set_margin_end( gtk_widget , right_margin_width );
	return;;
}

void SetGtkGridSpaceWidth( GtkWidget *gtk_widget , int row_spacing_width , int column_spacing_width )
{
	gtk_grid_set_row_spacing( GTK_GRID(gtk_widget) , row_spacing_width );
	gtk_grid_set_column_spacing( GTK_GRID(gtk_widget) , column_spacing_width );
	return;
}

int TransferMasterObjectToOutputObject( struct ZlangRuntime *rt , struct ZlangObject *out_obj , struct ZlangObject *master_obj )
{
	char		*obj_name = NULL ;
	int		nret ;

	nret = ReferObject( rt , out_obj , master_obj ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}
	
	obj_name = GetObjectName( master_obj ) ;
	if( obj_name )
	{
		nret = SetObjectName( rt , out_obj , obj_name ) ;
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "SetObjectName failed[%d]" , nret )
			return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_SET_OBJECT_NAME_FAILED );
		}
	}

	return 0;
}

struct ZlangObject *TransferInputObjectToNewObject( struct ZlangRuntime *rt , struct ZlangObject *in_obj )
{
	struct ZlangObject				*new_obj = NULL ;
	char						*obj_name = NULL ;

	int						nret ;

	new_obj = AllocObject( rt ) ;
	if( new_obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "AllocObject failed" )
		ThrowErrorException( rt , ZLANG_ERROR_ALLOC , EXCEPTION_MESSAGE_ALLOC_OBJECT_FAILED );
		return NULL;
	}

	nret = ReferObject( rt , new_obj , in_obj ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		DestroyObject( rt , new_obj );
		ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
		return NULL;
	}
	
	obj_name = GetObjectName( in_obj ) ;
	if( obj_name )
	{
		nret = SetObjectName( rt , new_obj , obj_name ) ;
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "SetObjectName failed[%d]" , nret )
			DestroyObject( rt , new_obj );
			ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_SET_OBJECT_NAME_FAILED );
			return NULL;
		}
	}

	return new_obj;
}

void OnGtkDialogResponseEventProc( GtkDialog *gtk_dialog , gint response_id, gpointer data )
{
	struct DialogResponseContext	*response_ctx = (struct DialogResponseContext *)data ;

	response_ctx->response_id = response_id ;

	g_main_loop_quit( response_ctx->main_loop );

	return;
}

int GtkDialogRun( struct ZlangRuntime *rt , GtkDialog *gtk_dialog )
{
	struct DialogResponseContext		response_ctx = { NULL , 0 } ;

	response_ctx.main_loop = g_main_loop_new( NULL , FALSE ) ;
	if( response_ctx.main_loop == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "g_main_loop_new failed" )
		ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_ALLOC_FAILED );
		return 0;
	}

	g_signal_connect( gtk_dialog , "response" , G_CALLBACK(OnGtkDialogResponseEventProc) , & response_ctx );
	gtk_widget_show( GTK_WIDGET(gtk_dialog) );
	
	g_main_loop_run( response_ctx.main_loop );

	gtk_widget_hide( GTK_WIDGET(gtk_dialog) );
	g_main_loop_unref( response_ctx.main_loop );

	return response_ctx.response_id;
}

int GtkNativeDialogRun( struct ZlangRuntime *rt , GtkNativeDialog *gtk_dialog )
{
	struct DialogResponseContext		response_ctx = { NULL , 0 } ;

	response_ctx.main_loop = g_main_loop_new( NULL , FALSE ) ;
	if( response_ctx.main_loop == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "g_main_loop_new failed" )
		ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_ALLOC_FAILED );
		return 0;
	}

	g_signal_connect( gtk_dialog , "response" , G_CALLBACK(OnGtkDialogResponseEventProc) , & response_ctx );
	gtk_native_dialog_show( gtk_dialog );
	
	g_main_loop_run( response_ctx.main_loop );

	gtk_native_dialog_hide( gtk_dialog );
	g_main_loop_unref( response_ctx.main_loop );

	return response_ctx.response_id;
}

GtkWidget *GetControlParentGtkWidget( struct ZlangDirectProperty_guiwidget_common *guictl_common )
{
	if( guictl_common->gtk_event_box )
		return guictl_common->gtk_event_box;
	else if( guictl_common->gtk_frame )
		return guictl_common->gtk_frame;
	else if( guictl_common->gtk_alignment )
		return guictl_common->gtk_alignment;
	/*
	else if( guictl_common->gtk_outer_widget )
		return guictl_common->gtk_outer_widget;
	*/
	else
		return guictl_common->gtk_widget;
}

GtkWidget *GetControlGtkEventBoxOrInnerOrWidget( struct ZlangDirectProperty_guiwidget_common *guictl_common )
{
	if( guictl_common->gtk_inner )
		return guictl_common->gtk_inner;
	else if( guictl_common->gtk_event_box )
		return guictl_common->gtk_event_box;
	else
		return guictl_common->gtk_widget;
}

struct WindowControlGroup *GetGtkControlGroup( struct ZlangRuntime *rt , struct ZlangObject *guiwindow_obj , char *group_name )
{
	struct ZlangDirectProperty_guiwindow	*guiwindow_direct_prop = GetObjectDirectProperty(guiwindow_obj) ;
	struct WindowControlGroup		*win_ctl_grp = NULL ;

	if( group_name == NULL )
		return NULL;

	list_for_each_entry( win_ctl_grp , & (guiwindow_direct_prop->win_ctl_grp_list) , struct WindowControlGroup , win_ctl_grp_list_node )
	{
		if( STRCMP( win_ctl_grp->group_name , == , group_name ) )
			return win_ctl_grp;
	}

	return NULL;
}

struct WindowControlGroup *AddGtkControlGroup( struct ZlangRuntime *rt , struct ZlangObject *guiwindow_obj , char *group_name )
{
	struct ZlangDirectProperty_guiwindow	*guiwindow_direct_prop = GetObjectDirectProperty(guiwindow_obj) ;
	struct WindowControlGroup		*gtk_ctl_grp = NULL ;

	if( group_name == NULL )
		return NULL;

	gtk_ctl_grp = malloc( sizeof(struct WindowControlGroup) ) ;
	if( gtk_ctl_grp == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc failed" )
		ThrowErrorException( rt , ZLANG_ERROR_ALLOC , EXCEPTION_MESSAGE_ALLOC_FAILED );
		return NULL;
	}
	memset( gtk_ctl_grp , 0x00 , sizeof(struct WindowControlGroup) );
	gtk_ctl_grp->group_name = strdup( group_name ) ;
	if( gtk_ctl_grp->group_name == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc failed" )
		ThrowErrorException( rt , ZLANG_ERROR_ALLOC , EXCEPTION_MESSAGE_ALLOC_FAILED );
		return NULL;
	}

	list_add_tail( & (gtk_ctl_grp->win_ctl_grp_list_node) , & (guiwindow_direct_prop->win_ctl_grp_list) );

	return gtk_ctl_grp;
}

int AddGtkWidgetToGsList( struct ZlangRuntime *rt , GSList **gtk_widget_list , GtkWidget *gtk_widget )
{
	GSList	*new_gtk_widget_list = NULL ;

	new_gtk_widget_list = g_slist_append( (*gtk_widget_list) , gtk_widget ) ;
	if( new_gtk_widget_list == NULL )
		return -1;
	(*gtk_widget_list) = new_gtk_widget_list ;
	return 0;
}

int GetGtkListSelectedRow( struct ZlangRuntime *rt , GSList *gtk_widget_list )
{
	GSList		*iter = NULL ;
	GtkWidget	*widget = NULL ;
	int		index ;

	for( iter = gtk_widget_list , index = 0 ; iter ; iter = g_slist_next(iter) , index++ )
	{
		widget = GTK_WIDGET(iter->data) ;
		if( gtk_check_button_get_active( GTK_CHECK_BUTTON(widget) ) )
			return index;
	}

	return -1;
}

GtkWidget *GetGtkListSelectedWidget( struct ZlangRuntime *rt , GSList *gtk_widget_list )
{
	GSList		*iter = NULL ;
	GtkWidget	*widget = NULL ;

	for( iter = gtk_widget_list ; iter ; iter = g_slist_next(iter) )
	{
		widget = GTK_WIDGET(iter->data) ;
		if( gtk_check_button_get_active( GTK_CHECK_BUTTON(widget) ) )
			return widget;
	}

	return NULL;
}

void QuitGtkMainLoop( struct ZlangObject *guiwindow_obj )
{
	struct ZlangDirectProperty_guiwindow		*guiwindow_direct_prop = GetObjectDirectProperty(guiwindow_obj) ;
	struct ZlangDirectProperty_guiwidget_common	*guiwindow_common = (struct ZlangDirectProperty_guiwidget_common *)guiwindow_direct_prop ;

	gtk_window_close( GTK_WINDOW(guiwindow_common->gtk_widget) );

	return;
}

int AddWindowGeneralEventCallback( struct ZlangRuntime *rt , struct ZlangObject *guiwindow_obj , char *event_name , struct ZlangObject *funcp )
{
	struct ZlangDirectProperty_guiwindow		*guiwindow_obj_direct_prop = GetObjectDirectProperty(guiwindow_obj) ;
	struct ZlangDirectProperty_guiwidget_common	*guiwindow_common = (struct ZlangDirectProperty_guiwidget_common *)guiwindow_obj_direct_prop ;
	struct ZlangObject				*new_funcp = NULL ;
	struct ZlangObject				*new_guiwindow_obj = NULL ;
	struct WindowCallbackContext			*win_callback_ctx = NULL ;
	
	new_funcp = TransferInputObjectToNewObject( rt , funcp ) ;
	if( new_funcp == NULL )
		return GetRuntimeErrorNo(rt);

	new_guiwindow_obj = TransferInputObjectToNewObject( rt , guiwindow_obj ) ;
	if( new_guiwindow_obj == NULL )
		return GetRuntimeErrorNo(rt);

	win_callback_ctx = malloc( sizeof(struct WindowCallbackContext) ) ;
	if( win_callback_ctx == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc failed" )
		return ThrowErrorException( rt , ZLANG_ERROR_ALLOC , EXCEPTION_MESSAGE_ALLOC_FAILED );
	}
	memset( win_callback_ctx , 0x00 , sizeof(struct WindowCallbackContext) );
	win_callback_ctx->event_name = event_name ;
	win_callback_ctx->funcp = new_funcp ;
	win_callback_ctx->rt = rt ;
	win_callback_ctx->guiwindow_obj = new_guiwindow_obj ;
	list_add_tail( & (win_callback_ctx->win_callback_ctx_list_node) , & (guiwindow_obj_direct_prop->win_gene_callback_ctx_list) );

	if( guiwindow_obj_direct_prop->is_showed == TRUE )
	{
		g_signal_connect( guiwindow_common->gtk_widget , win_callback_ctx->event_name , G_CALLBACK(OnGtkWindowGeneralEventProc) , win_callback_ctx );
	}

	return 0;
}

void OnGtkWindowGeneralEventProc( GtkWidget *widget , gpointer data )
{
	InvokeGtkWindowEventCallbackFunction( (struct WindowCallbackContext *)data );

	return;
}

int InvokeGtkWindowEventCallbackFunction( struct WindowCallbackContext *win_callback_event )
{
	struct ZlangRuntime		*rt = win_callback_event->rt ;
	struct ZlangObject		*guiwindow_obj = win_callback_event->guiwindow_obj ;
	char				*event_name = win_callback_event->event_name ;
	struct ZlangObject		*in_obj = NULL ;
	struct ZlangFunction		*func = NULL ;

	struct ZlangObject		*obj = NULL ;
	struct ZlangObjectsStackFrame	*curr_objs_stack_frame = NULL ;
	struct ZlangFunctionParameter	*func_param_guiwindow = NULL ;
	struct ZlangFunctionParameter	*func_param_guievent = NULL ;

	int				nret = 0 ;

	CallRuntimeFunction_functionptr_GetObjectPtr( rt , win_callback_event->funcp , & in_obj );
	CallRuntimeFunction_functionptr_GetFunctionPtr( rt , win_callback_event->funcp , & func );

	func_param_guiwindow = TravelFunctionInputParameter( rt , func , NULL ) ;
	if( func_param_guiwindow == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guiwindow) , != , "guiwindow" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guievent = TravelFunctionInputParameter( rt , func , func_param_guiwindow ) ;
	if( func_param_guievent == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guievent) , != , "string" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	IncreaseStackFrame( rt , GetFunctionName(func) ) ;
	curr_objs_stack_frame = GetCurrentLocalObjectsStackFrame( rt ) ;

	obj = ReferObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guiwindow) , guiwindow_obj ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}

	obj = CloneStringObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guievent) ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneStringObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}
	nret = CallRuntimeFunction_string_SetStringValue( rt , obj , event_name , STRLEN_OF_STRING ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_string_SetStringValue failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_SET_STRING_VALUE_FAILED );
	}

	MarkInputParamtersTop( curr_objs_stack_frame );

	MarkOutputParamtersTop( curr_objs_stack_frame );

	nret = InvokeEntryFunction( rt , in_obj , func ) ;
	DecreaseStackFrame( rt );
	if( nret )
	{
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_INVOKE_ENTRY_FUNCTION_FAILED );
	}

	return 0;
}

int AddWindowFocusEventCallback( struct ZlangRuntime *rt , struct ZlangObject *guiwindow_obj , char *event_name , struct ZlangObject *funcp )
{
	struct ZlangDirectProperty_guiwindow		*guiwindow_obj_direct_prop = GetObjectDirectProperty(guiwindow_obj) ;
	struct ZlangDirectProperty_guiwidget_common	*guiwindow_common = (struct ZlangDirectProperty_guiwidget_common *)guiwindow_obj_direct_prop ;
	struct ZlangObject				*new_funcp = NULL ;
	struct ZlangObject				*new_guiwindow_obj = NULL ;
	struct WindowCallbackContext			*win_callback_ctx = NULL ;
	
	new_funcp = TransferInputObjectToNewObject( rt , funcp ) ;
	if( new_funcp == NULL )
		return GetRuntimeErrorNo(rt);

	new_guiwindow_obj = TransferInputObjectToNewObject( rt , guiwindow_obj ) ;
	if( new_guiwindow_obj == NULL )
		return GetRuntimeErrorNo(rt);

	win_callback_ctx = malloc( sizeof(struct WindowCallbackContext) ) ;
	if( win_callback_ctx == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc failed" )
		return ThrowErrorException( rt , ZLANG_ERROR_ALLOC , EXCEPTION_MESSAGE_ALLOC_FAILED );
	}
	memset( win_callback_ctx , 0x00 , sizeof(struct WindowCallbackContext) );
	win_callback_ctx->event_name = event_name ;
	win_callback_ctx->funcp = new_funcp ;
	win_callback_ctx->rt = rt ;
	win_callback_ctx->guiwindow_obj = new_guiwindow_obj ;
	list_add_tail( & (win_callback_ctx->win_callback_ctx_list_node) , & (guiwindow_obj_direct_prop->win_focus_callback_ctx_list) );

	if( guiwindow_obj_direct_prop->is_showed == TRUE )
	{
		g_signal_connect( guiwindow_common->gtk_widget , win_callback_ctx->event_name , G_CALLBACK(OnGtkWindowFocusEventProc) , win_callback_ctx );
	}

	return 0;
}

void OnGtkWindowFocusEventProc( GtkWidget *widget , gpointer data )
{
	struct WindowCallbackContext	*win_callback_ctx = (struct WindowCallbackContext *)data ;

	InvokeGtkWindowEventCallbackFunction( win_callback_ctx );

	return;
}

void OnGtkWindowUnfocusEventProc( GtkWidget *widget , gpointer data )
{
	struct WindowCallbackContext	*win_callback_ctx = (struct WindowCallbackContext *)data ;

	InvokeGtkWindowEventCallbackFunction( win_callback_ctx );

	return;
}

int AddWindowKeyEventCallback( struct ZlangRuntime *rt , struct ZlangObject *guiwindow_obj , char *event_name , struct ZlangObject *funcp )
{
	struct ZlangDirectProperty_guiwindow		*guiwindow_obj_direct_prop = GetObjectDirectProperty(guiwindow_obj) ;
	struct ZlangDirectProperty_guiwidget_common	*guiwindow_common = (struct ZlangDirectProperty_guiwidget_common *)guiwindow_obj_direct_prop ;
	struct ZlangObject				*new_funcp = NULL ;
	struct ZlangObject				*new_guiwindow_obj = NULL ;
	struct WindowCallbackContext			*win_callback_ctx = NULL ;
	
	new_funcp = TransferInputObjectToNewObject( rt , funcp ) ;
	if( new_funcp == NULL )
		return GetRuntimeErrorNo(rt);

	new_guiwindow_obj = TransferInputObjectToNewObject( rt , guiwindow_obj ) ;
	if( new_guiwindow_obj == NULL )
		return GetRuntimeErrorNo(rt);

	win_callback_ctx = malloc( sizeof(struct WindowCallbackContext) ) ;
	if( win_callback_ctx == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc failed" )
		return ThrowErrorException( rt , ZLANG_ERROR_ALLOC , EXCEPTION_MESSAGE_ALLOC_FAILED );
	}
	memset( win_callback_ctx , 0x00 , sizeof(struct WindowCallbackContext) );
	win_callback_ctx->event_name = event_name ;
	win_callback_ctx->funcp = new_funcp ;
	win_callback_ctx->rt = rt ;
	win_callback_ctx->guiwindow_obj = new_guiwindow_obj ;
	list_add_tail( & (win_callback_ctx->win_callback_ctx_list_node) , & (guiwindow_obj_direct_prop->win_key_callback_ctx_list) );

	if( guiwindow_obj_direct_prop->is_showed == TRUE )
	{
		GtkEventController *controller = gtk_event_controller_key_new() ;
		g_signal_connect( controller , win_callback_ctx->event_name , G_CALLBACK(OnGtkWindowKeyEventProc) , win_callback_ctx );
		gtk_widget_add_controller( guiwindow_common->gtk_widget , controller );
	}

	return 0;
}

gboolean OnGtkWindowKeyEventProc( GtkWidget *widget , guint keyval , guint keycode , GdkModifierType state , gpointer data )
{
	struct WindowCallbackContext		*win_callback_ctx = (struct WindowCallbackContext *)data ;
	
	win_callback_ctx->key_state = state ;
	win_callback_ctx->key_val = keyval ;

	InvokeGtkWindowKeyEventCallbackFunction( win_callback_ctx );

	return win_callback_ctx->ret_bool;
}

int InvokeGtkWindowKeyEventCallbackFunction( struct WindowCallbackContext *win_callback_event )
{
	struct ZlangRuntime		*rt = win_callback_event->rt ;
	struct ZlangObject		*guiwindow_obj = win_callback_event->guiwindow_obj ;
	// char				*event_name = win_callback_event->event_name ;
	struct ZlangObject		*in_obj = NULL ;
	struct ZlangFunction		*func = NULL ;

	struct ZlangObject		*obj = NULL ;
	struct ZlangObjectsStackFrame	*curr_objs_stack_frame = NULL ;
	struct ZlangFunctionParameter	*func_param_guiwindow = NULL ;
	struct ZlangFunctionParameter	*func_param_key_state = NULL ;
	struct ZlangFunctionParameter	*func_param_key_val = NULL ;
	struct ZlangFunctionParameter	*func_param_output = NULL ;

	int				nret = 0 ;

	CallRuntimeFunction_functionptr_GetObjectPtr( rt , win_callback_event->funcp , & in_obj );
	CallRuntimeFunction_functionptr_GetFunctionPtr( rt , win_callback_event->funcp , & func );

	func_param_output = GetFunctionOutParameter( func ) ;
	if( func_param_output == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] output params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_output) , != , ZLANG_OBJECT_bool ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] output param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guiwindow = TravelFunctionInputParameter( rt , func , NULL ) ;
	if( func_param_guiwindow == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guiwindow) , != , "guiwindow" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_key_state = TravelFunctionInputParameter( rt , func , func_param_guiwindow ) ;
	if( func_param_key_state == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_key_state) , != , "int" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_key_val = TravelFunctionInputParameter( rt , func , func_param_key_state ) ;
	if( func_param_key_val == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_key_val) , != , "int" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	IncreaseStackFrame( rt , GetFunctionName(func) ) ;
	curr_objs_stack_frame = GetCurrentLocalObjectsStackFrame( rt ) ;

	obj = ReferObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guiwindow) , guiwindow_obj ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}

	obj = CloneIntObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_key_state) ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneIntObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}
	nret = CallRuntimeFunction_int_SetIntValue( rt , obj , win_callback_event->key_state ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_int_SetIntValue failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_SET_STRING_VALUE_FAILED );
	}

	obj = CloneIntObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_key_val) ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneIntObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}
	nret = CallRuntimeFunction_int_SetIntValue( rt , obj , win_callback_event->key_val ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_int_SetIntValue failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_SET_STRING_VALUE_FAILED );
	}

	MarkInputParamtersTop( curr_objs_stack_frame );

	obj = CloneBoolObjectInLocalStack( rt , NULL ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneBoolObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}

	MarkOutputParamtersTop( curr_objs_stack_frame );

	nret = InvokeEntryFunction( rt , in_obj , func ) ;
	IsObjectTrueValue( rt , GetOutputParameterInLocalObjectStack(rt,1) , & (win_callback_event->ret_bool) );
	DecreaseStackFrame( rt );
	if( nret )
	{
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_INVOKE_ENTRY_FUNCTION_FAILED );
	}

	return 0;
}

int AddWindowMouseButtonEventCallback( struct ZlangRuntime *rt , struct ZlangObject *guiwindow_obj , char *event_name , struct ZlangObject *funcp )
{
	struct ZlangDirectProperty_guiwindow		*guiwindow_obj_direct_prop = GetObjectDirectProperty(guiwindow_obj) ;
	struct ZlangDirectProperty_guiwidget_common	*guiwindow_common = (struct ZlangDirectProperty_guiwidget_common *)guiwindow_obj_direct_prop ;
	struct ZlangObject				*new_funcp = NULL ;
	struct ZlangObject				*new_guiwindow_obj = NULL ;
	struct WindowCallbackContext			*win_callback_ctx = NULL ;
	
	new_funcp = TransferInputObjectToNewObject( rt , funcp ) ;
	if( new_funcp == NULL )
		return GetRuntimeErrorNo(rt);

	new_guiwindow_obj = TransferInputObjectToNewObject( rt , guiwindow_obj ) ;
	if( new_guiwindow_obj == NULL )
		return GetRuntimeErrorNo(rt);

	win_callback_ctx = malloc( sizeof(struct WindowCallbackContext) ) ;
	if( win_callback_ctx == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc failed" )
		return ThrowErrorException( rt , ZLANG_ERROR_ALLOC , EXCEPTION_MESSAGE_ALLOC_FAILED );
	}
	memset( win_callback_ctx , 0x00 , sizeof(struct WindowCallbackContext) );
	win_callback_ctx->event_name = event_name ;
	win_callback_ctx->funcp = new_funcp ;
	win_callback_ctx->rt = rt ;
	win_callback_ctx->guiwindow_obj = new_guiwindow_obj ;
	list_add_tail( & (win_callback_ctx->win_callback_ctx_list_node) , & (guiwindow_obj_direct_prop->win_mouse_button_callback_ctx_list) );

	if( guiwindow_obj_direct_prop->is_showed == TRUE )
	{
		GtkGesture *gesture = gtk_gesture_click_new();
		gtk_gesture_single_set_button( GTK_GESTURE_SINGLE(gesture) , 0 );
		g_signal_connect( gesture , win_callback_ctx->event_name , G_CALLBACK(OnGtkWindowMouseButtonEventProc) , win_callback_ctx );
		gtk_widget_add_controller( guiwindow_common->gtk_widget , GTK_EVENT_CONTROLLER(gesture) );
	}

	return 0;
}

bool OnGtkWindowMouseButtonEventProc( GtkGestureClick *gesture , int n_press , double x , double y , gpointer user_data )
{
	struct WindowCallbackContext		*win_callback_ctx = (struct WindowCallbackContext *)user_data ;

	win_callback_ctx->button_type = gtk_gesture_single_get_current_button(GTK_GESTURE_SINGLE(gesture)) ;
	win_callback_ctx->n_press = n_press ;
	win_callback_ctx->x = (int)x ;
	win_callback_ctx->y = (int)y ;

	InvokeGtkWindowMouseButtonEventCallbackFunction( win_callback_ctx );

	return win_callback_ctx->ret_bool;
}

int InvokeGtkWindowMouseButtonEventCallbackFunction( struct WindowCallbackContext *win_callback_event )
{
	struct ZlangRuntime		*rt = win_callback_event->rt ;
	struct ZlangObject		*guiwindow_obj = win_callback_event->guiwindow_obj ;
	// char				*event_name = win_callback_event->event_name ;
	struct ZlangObject		*in_obj = NULL ;
	struct ZlangFunction		*func = NULL ;

	struct ZlangObject		*obj = NULL ;
	struct ZlangFunctionParameter	*func_param_output = NULL ;
	struct ZlangObjectsStackFrame	*curr_objs_stack_frame = NULL ;
	struct ZlangFunctionParameter	*func_param_guiwindow = NULL ;
	struct ZlangFunctionParameter	*func_param_button_type = NULL ;
	struct ZlangFunctionParameter	*func_param_n_press = NULL ;
	struct ZlangFunctionParameter	*func_param_x = NULL ;
	struct ZlangFunctionParameter	*func_param_y = NULL ;

	int				nret = 0 ;

	CallRuntimeFunction_functionptr_GetObjectPtr( rt , win_callback_event->funcp , & in_obj );
	CallRuntimeFunction_functionptr_GetFunctionPtr( rt , win_callback_event->funcp , & func );

	func_param_output = GetFunctionOutParameter( func ) ;
	if( func_param_output == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] output params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_output) , != , "bool" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] output param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guiwindow = TravelFunctionInputParameter( rt , func , NULL ) ;
	if( func_param_guiwindow == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guiwindow) , != , "guiwindow" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_button_type = TravelFunctionInputParameter( rt , func , func_param_guiwindow ) ;
	if( func_param_button_type == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_button_type) , != , "int" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_n_press = TravelFunctionInputParameter( rt , func , func_param_button_type ) ;
	if( func_param_n_press == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_n_press) , != , "int" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_x = TravelFunctionInputParameter( rt , func , func_param_n_press ) ;
	if( func_param_x == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_x) , != , "int" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_y = TravelFunctionInputParameter( rt , func , func_param_x ) ;
	if( func_param_y == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_y) , != , "int" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	IncreaseStackFrame( rt , GetFunctionName(func) ) ;
	curr_objs_stack_frame = GetCurrentLocalObjectsStackFrame( rt ) ;

	obj = ReferObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guiwindow) , guiwindow_obj ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}

	obj = CloneIntObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_button_type) ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneIntObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}
	nret = CallRuntimeFunction_int_SetIntValue( rt , obj , win_callback_event->button_type ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_int_SetIntValue failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_SET_STRING_VALUE_FAILED );
	}

	obj = CloneIntObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_n_press) ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneIntObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}
	nret = CallRuntimeFunction_int_SetIntValue( rt , obj , win_callback_event->n_press ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_int_SetIntValue failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_SET_STRING_VALUE_FAILED );
	}

	obj = CloneIntObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_x) ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneIntObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}
	nret = CallRuntimeFunction_int_SetIntValue( rt , obj , win_callback_event->x ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_int_SetIntValue failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_SET_STRING_VALUE_FAILED );
	}

	obj = CloneIntObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_y) ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneIntObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}
	nret = CallRuntimeFunction_int_SetIntValue( rt , obj , win_callback_event->y ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_int_SetIntValue failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_SET_STRING_VALUE_FAILED );
	}

	MarkInputParamtersTop( curr_objs_stack_frame );

	obj = CloneBoolObjectInLocalStack( rt , NULL ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneBoolObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}

	MarkOutputParamtersTop( curr_objs_stack_frame );

	nret = InvokeEntryFunction( rt , in_obj , func ) ;
	IsObjectTrueValue( rt , GetOutputParameterInLocalObjectStack(rt,1) , & (win_callback_event->ret_bool) );
	DecreaseStackFrame( rt );
	if( nret )
	{
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_INVOKE_ENTRY_FUNCTION_FAILED );
	}

	return 0;
}

int SetWindowStateEventCallback( struct ZlangRuntime *rt , struct ZlangObject *guiwindow_obj , char *event_name , struct ZlangObject *funcp )
{
	struct ZlangDirectProperty_guiwindow		*guiwindow_obj_direct_prop = GetObjectDirectProperty(guiwindow_obj) ;
	struct ZlangDirectProperty_guiwidget_common	*guiwindow_common = (struct ZlangDirectProperty_guiwidget_common *)guiwindow_obj_direct_prop ;
	struct ZlangObject				*new_funcp = NULL ;
	struct ZlangObject				*new_guiwindow_obj = NULL ;
	struct WindowCallbackContext			*win_callback_ctx = NULL ;
	
	new_funcp = TransferInputObjectToNewObject( rt , funcp ) ;
	if( new_funcp == NULL )
		return GetRuntimeErrorNo(rt);

	new_guiwindow_obj = TransferInputObjectToNewObject( rt , guiwindow_obj ) ;
	if( new_guiwindow_obj == NULL )
		return GetRuntimeErrorNo(rt);

	win_callback_ctx = malloc( sizeof(struct WindowCallbackContext) ) ;
	if( win_callback_ctx == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc failed" )
		return ThrowErrorException( rt , ZLANG_ERROR_ALLOC , EXCEPTION_MESSAGE_ALLOC_FAILED );
	}
	memset( win_callback_ctx , 0x00 , sizeof(struct WindowCallbackContext) );
	win_callback_ctx->event_name = event_name ;
	win_callback_ctx->funcp = new_funcp ;
	win_callback_ctx->rt = rt ;
	win_callback_ctx->guiwindow_obj = new_guiwindow_obj ;
	list_add_tail( & (win_callback_ctx->win_callback_ctx_list_node) , & (guiwindow_obj_direct_prop->win_state_callback_ctx_list) );

	if( guiwindow_obj_direct_prop->is_showed == TRUE )
	{
		g_signal_connect( guiwindow_common->gtk_widget , win_callback_ctx->event_name , G_CALLBACK(OnGtkWindowStateEventProc) , win_callback_ctx );
	}

	return 0;
}

void OnGtkWindowStateEventProc( GtkWidget *widget , GParamSpec *pspec , gpointer user_data )
{
	struct WindowCallbackContext		*win_callback_ctx = (struct WindowCallbackContext *)user_data ;

	InvokeGtkWindowStateEventCallbackFunction( win_callback_ctx );

	return;
}

int InvokeGtkWindowStateEventCallbackFunction( struct WindowCallbackContext *win_callback_event )
{
	struct ZlangRuntime		*rt = win_callback_event->rt ;
	struct ZlangObject		*guiwindow_obj = win_callback_event->guiwindow_obj ;
	// char				*event_name = win_callback_event->event_name ;
	struct ZlangObject		*in_obj = NULL ;
	struct ZlangFunction		*func = NULL ;

	struct ZlangObject		*obj = NULL ;
	struct ZlangObjectsStackFrame	*curr_objs_stack_frame = NULL ;
	struct ZlangFunctionParameter	*func_param_guiwindow = NULL ;
	struct ZlangFunctionParameter	*func_param_output = NULL ;

	int				nret = 0 ;

	CallRuntimeFunction_functionptr_GetObjectPtr( rt , win_callback_event->funcp , & in_obj );
	CallRuntimeFunction_functionptr_GetFunctionPtr( rt , win_callback_event->funcp , & func );

	func_param_output = GetFunctionOutParameter( func ) ;
	if( func_param_output == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] output params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_output) , != , "void" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] output param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guiwindow = TravelFunctionInputParameter( rt , func , NULL ) ;
	if( func_param_guiwindow == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guiwindow) , != , "guiwindow" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	IncreaseStackFrame( rt , GetFunctionName(func) ) ;
	curr_objs_stack_frame = GetCurrentLocalObjectsStackFrame( rt ) ;

	obj = ReferObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guiwindow) , guiwindow_obj ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}

	MarkInputParamtersTop( curr_objs_stack_frame );

	MarkOutputParamtersTop( curr_objs_stack_frame );

	nret = InvokeEntryFunction( rt , in_obj , func ) ;
	DecreaseStackFrame( rt );
	if( nret )
	{
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_INVOKE_ENTRY_FUNCTION_FAILED );
	}

	return 0;
}

int SetCloseWindowEventCallback( struct ZlangRuntime *rt , struct ZlangObject *guiwindow_obj , char *event_name , struct ZlangObject *funcp )
{
	struct ZlangDirectProperty_guiwindow		*guiwindow_obj_direct_prop = GetObjectDirectProperty(guiwindow_obj) ;
	struct ZlangDirectProperty_guiwidget_common	*guiwindow_common = (struct ZlangDirectProperty_guiwidget_common *)guiwindow_obj_direct_prop ;
	struct ZlangObject				*new_funcp = NULL ;
	struct ZlangObject				*new_guiwindow_obj = NULL ;
	struct WindowCallbackContext			*win_callback_ctx = NULL ;
	
	new_funcp = TransferInputObjectToNewObject( rt , funcp ) ;
	if( new_funcp == NULL )
		return GetRuntimeErrorNo(rt);

	new_guiwindow_obj = TransferInputObjectToNewObject( rt , guiwindow_obj ) ;
	if( new_guiwindow_obj == NULL )
		return GetRuntimeErrorNo(rt);

	win_callback_ctx = malloc( sizeof(struct WindowCallbackContext) ) ;
	if( win_callback_ctx == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc failed" )
		return ThrowErrorException( rt , ZLANG_ERROR_ALLOC , EXCEPTION_MESSAGE_ALLOC_FAILED );
	}
	memset( win_callback_ctx , 0x00 , sizeof(struct WindowCallbackContext) );
	win_callback_ctx->event_name = event_name ;
	win_callback_ctx->funcp = new_funcp ;
	win_callback_ctx->rt = rt ;
	win_callback_ctx->guiwindow_obj = new_guiwindow_obj ;
	guiwindow_obj_direct_prop->win_close_callback_ctx = win_callback_ctx ;

	if( guiwindow_obj_direct_prop->is_showed == TRUE )
	{
		g_signal_connect( guiwindow_common->gtk_widget , guiwindow_obj_direct_prop->win_close_callback_ctx->event_name , G_CALLBACK(OnGtkCloseWindowEventProc) , guiwindow_obj_direct_prop->win_close_callback_ctx );
	}

	return 0;
}

gboolean OnGtkCloseWindowEventProc( GtkWidget *widget , gpointer data )
{
	struct WindowCallbackContext		*win_callback_ctx = (struct WindowCallbackContext *)data ;
	struct ZlangDirectProperty_guiwindow	*guiwindow_direct_prop = GetObjectDirectProperty(win_callback_ctx->guiwindow_obj) ;

	InvokeGtkCloseWindowEventCallbackFunction( win_callback_ctx );

	if( ! win_callback_ctx->ret_bool )
		g_main_loop_quit( guiwindow_direct_prop->main_loop );

	return win_callback_ctx->ret_bool;
}

int InvokeGtkCloseWindowEventCallbackFunction( struct WindowCallbackContext *win_callback_event )
{
	struct ZlangRuntime		*rt = win_callback_event->rt ;
	struct ZlangObject		*guiwindow_obj = win_callback_event->guiwindow_obj ;
	// char				*event_name = win_callback_event->event_name ;
	struct ZlangObject		*in_obj = NULL ;
	struct ZlangFunction		*func = NULL ;

	struct ZlangObject		*obj = NULL ;
	struct ZlangObjectsStackFrame	*curr_objs_stack_frame = NULL ;
	struct ZlangFunctionParameter	*func_param_guiwindow = NULL ;
	struct ZlangFunctionParameter	*func_param_output = NULL ;

	int				nret = 0 ;

	CallRuntimeFunction_functionptr_GetObjectPtr( rt , win_callback_event->funcp , & in_obj );
	CallRuntimeFunction_functionptr_GetFunctionPtr( rt , win_callback_event->funcp , & func );

	func_param_output = GetFunctionOutParameter( func ) ;
	if( func_param_output == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] output params count not matched" , GetFunctionName(func) )
		win_callback_event->ret_bool = TRUE ;
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_output) , != , "bool" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] output param type not matched" , GetFunctionName(func) )
		win_callback_event->ret_bool = TRUE ;
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guiwindow = TravelFunctionInputParameter( rt , func , NULL ) ;
	if( func_param_guiwindow == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		win_callback_event->ret_bool = TRUE ;
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guiwindow) , != , "guiwindow" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		win_callback_event->ret_bool = TRUE ;
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	IncreaseStackFrame( rt , GetFunctionName(func) ) ;
	curr_objs_stack_frame = GetCurrentLocalObjectsStackFrame( rt ) ;

	obj = ReferObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guiwindow) , guiwindow_obj ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		win_callback_event->ret_bool = TRUE ;
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}

	MarkInputParamtersTop( curr_objs_stack_frame );

	obj = CloneBoolObjectInLocalStack( rt , NULL ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneBoolObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}

	MarkOutputParamtersTop( curr_objs_stack_frame );

	nret = InvokeEntryFunction( rt , in_obj , func ) ;
	IsObjectTrueValue( rt , GetOutputParameterInLocalObjectStack(rt,1) , & (win_callback_event->ret_bool) );
	DecreaseStackFrame( rt );
	if( nret )
	{
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_INVOKE_ENTRY_FUNCTION_FAILED );
	}

	return 0;
}

gboolean OnGtkCloseWindowEventProcDefault( GtkWidget *widget , gpointer data )
{
	struct ZlangDirectProperty_guiwindow	*guiwindow_direct_prop = (struct ZlangDirectProperty_guiwindow *)data ;

	g_main_loop_quit( guiwindow_direct_prop->main_loop );

	return TRUE;
}

gboolean OnGtkWindowTimerEventProc( gpointer data )
{
	struct WindowCallbackContext		*win_callback_ctx = (struct WindowCallbackContext *)data ;
	
	InvokeGtkWindowTimerEventCallbackFunction( win_callback_ctx );

	return win_callback_ctx->ret_bool;
}

int InvokeGtkWindowTimerEventCallbackFunction( struct WindowCallbackContext *win_callback_event )
{
	struct ZlangRuntime		*rt = win_callback_event->rt ;
	struct ZlangObject		*guiwindow_obj = win_callback_event->guiwindow_obj ;
	char				*timer_name = win_callback_event->event_name ;
	struct ZlangObject		*in_obj = NULL ;
	struct ZlangFunction		*func = NULL ;

	struct ZlangObject		*obj = NULL ;
	struct ZlangObjectsStackFrame	*curr_objs_stack_frame = NULL ;
	struct ZlangFunctionParameter	*func_param_output = NULL ;
	struct ZlangFunctionParameter	*func_param_guiwindow = NULL ;
	struct ZlangFunctionParameter	*func_param_guievent = NULL ;

	int				nret = 0 ;

	CallRuntimeFunction_functionptr_GetObjectPtr( rt , win_callback_event->funcp , & in_obj );
	CallRuntimeFunction_functionptr_GetFunctionPtr( rt , win_callback_event->funcp , & func );

	func_param_output = GetFunctionOutParameter( func ) ;
	if( func_param_output == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] output params count not matched" , GetFunctionName(func) )
		win_callback_event->ret_bool = TRUE ;
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_output) , != , "bool" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] output param type not matched" , GetFunctionName(func) )
		win_callback_event->ret_bool = TRUE ;
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guiwindow = TravelFunctionInputParameter( rt , func , NULL ) ;
	if( func_param_guiwindow == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guiwindow) , != , "guiwindow" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guievent = TravelFunctionInputParameter( rt , func , func_param_guiwindow ) ;
	if( func_param_guievent == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guievent) , != , "string" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	IncreaseStackFrame( rt , GetFunctionName(func) ) ;
	curr_objs_stack_frame = GetCurrentLocalObjectsStackFrame( rt ) ;

	obj = ReferObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guiwindow) , guiwindow_obj ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}

	obj = CloneStringObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guievent) ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneStringObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}
	nret = CallRuntimeFunction_string_SetStringValue( rt , obj , timer_name , STRLEN_OF_STRING ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_string_SetStringValue failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_SET_STRING_VALUE_FAILED );
	}

	MarkInputParamtersTop( curr_objs_stack_frame );

	obj = CloneBoolObjectInLocalStack( rt , NULL ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneBoolObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}

	MarkOutputParamtersTop( curr_objs_stack_frame );

	nret = InvokeEntryFunction( rt , in_obj , func ) ;
	IsObjectTrueValue( rt , GetOutputParameterInLocalObjectStack(rt,1) , & (win_callback_event->ret_bool) );
	DecreaseStackFrame( rt );
	if( nret )
	{
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_INVOKE_ENTRY_FUNCTION_FAILED );
	}

	return 0;
}

GtkWidget *TravelSlibingAndChildWidgets_QueryChildWithType( GType gtk_widget_type_id , GtkWidget *widget )
{
	GtkWidget		*child_widget = NULL ;
	GtkWidget		*slibing_widget = NULL ;
	GtkWidget		*return_widget = NULL ;

	if( gtk_widget_type_id == G_OBJECT_TYPE(widget) )
		return widget;

	child_widget = gtk_widget_get_first_child( widget ) ;
	if( child_widget )
	{
		return_widget = TravelSlibingAndChildWidgets_QueryChildWithType( gtk_widget_type_id , child_widget ) ;
		if( return_widget )
			return return_widget;
	}

	slibing_widget = gtk_widget_get_next_sibling( widget ) ;
	if( slibing_widget )
	{
		return_widget = TravelSlibingAndChildWidgets_QueryChildWithType( gtk_widget_type_id , slibing_widget ) ;
		if( return_widget )
			return return_widget;
	}

	return NULL;
}

int RegisteControlToWindow( struct ZlangRuntime *rt , struct ZlangObject *guiwindow_obj , struct ZlangObject *guictl_obj )
{
	struct ZlangDirectProperty_guiwindow		*guiwindow_obj_direct_prop = GetObjectDirectProperty(guiwindow_obj) ;
	struct ZlangDirectProperty_guiwidget_common	*guiwindow_common = (struct ZlangDirectProperty_guiwidget_common *)guiwindow_obj_direct_prop ;
	void						*guictl_obj_direct_prop = GetObjectDirectProperty(guictl_obj) ;
	struct ZlangDirectProperty_guiwidget_common	*guictl_common = (struct ZlangDirectProperty_guiwidget_common *)guictl_obj_direct_prop ;
	struct ZlangObject				*new_guictl_obj = NULL ;
	struct WindowCallbackControl			*win_callback_ctl = NULL ;

	new_guictl_obj = TransferInputObjectToNewObject( rt , guictl_obj ) ;
	if( new_guictl_obj == NULL )
		return GetRuntimeErrorNo(rt);

	// g_object_set_data( (GObject*)(guictl_common->gtk_widget) , WIDGET_ZOBJECT_NAME , GetObjectName(guictl_obj) );

	guictl_common->guiwindow_obj = guiwindow_obj ;

	win_callback_ctl = malloc( sizeof(struct WindowCallbackControl) ) ;
	if( win_callback_ctl == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc failed" )
		return ThrowErrorException( rt , ZLANG_ERROR_ALLOC , EXCEPTION_MESSAGE_ALLOC_FAILED );
	}
	memset( win_callback_ctl , 0x00 , sizeof(struct WindowCallbackControl) );
	win_callback_ctl->guictl_obj = new_guictl_obj ;
	list_add_tail( & (win_callback_ctl->win_callback_ctl_list_node) , & (guiwindow_obj_direct_prop->win_callback_ctl_list) );

	if( guiwindow_obj_direct_prop->is_showed == TRUE )
	{
		gtk_widget_show( guiwindow_common->gtk_widget );
	}

	return 0;
}

struct WindowCallbackControl *GetControlByName( struct ZlangObject *win_obj , char *search_obj_name )
{
	struct ZlangDirectProperty_guiwindow	*guiwindow_direct_prop = GetObjectDirectProperty(win_obj) ;
	struct WindowCallbackControl		*win_callback_ctl_obj = NULL ;
	char					*guictl_obj_name = NULL ;

	list_for_each_entry( win_callback_ctl_obj , & (guiwindow_direct_prop->win_callback_ctl_list) , struct WindowCallbackControl , win_callback_ctl_list_node )
	{
		guictl_obj_name = GetObjectName( win_callback_ctl_obj->guictl_obj ) ;
		if( guictl_obj_name && STRCMP( guictl_obj_name , == , search_obj_name ) )
		{
			return win_callback_ctl_obj;
		}
	}

	return NULL;
}

int AddControlGeneralEventCallback( struct ZlangRuntime *rt , struct ZlangObject *guiwindow_obj , struct ZlangObject *guictl_obj , char *event_name , struct ZlangObject *funcp )
{
	void						*guictl_obj_direct_prop = GetObjectDirectProperty(guictl_obj) ;
	struct ZlangDirectProperty_guiwidget_common	*guictl_common = (struct ZlangDirectProperty_guiwidget_common *)guictl_obj_direct_prop ;
	struct ZlangDirectProperty_guiwindow		*guiwindow_obj_direct_prop = GetObjectDirectProperty(guiwindow_obj) ;
	struct ZlangObject				*new_funcp = NULL ;
	struct ZlangObject				*new_guiwindow_obj = NULL ;
	struct ZlangObject				*new_guictl_obj = NULL ;
	struct ControlCallbackContext			*ctl_callback_ctx = NULL ;

	new_funcp = TransferInputObjectToNewObject( rt , funcp ) ;
	if( new_funcp == NULL )
		return GetRuntimeErrorNo(rt);

	new_guiwindow_obj = TransferInputObjectToNewObject( rt , guiwindow_obj ) ;
	if( new_guiwindow_obj == NULL )
		return GetRuntimeErrorNo(rt);

	new_guictl_obj = TransferInputObjectToNewObject( rt , guictl_obj ) ;
	if( new_guictl_obj == NULL )
		return GetRuntimeErrorNo(rt);

	ctl_callback_ctx = malloc( sizeof(struct ControlCallbackContext) ) ;
	if( ctl_callback_ctx == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc failed" )
		return ThrowErrorException( rt , ZLANG_ERROR_ALLOC , EXCEPTION_MESSAGE_ALLOC_FAILED );
	}
	memset( ctl_callback_ctx , 0x00 , sizeof(struct ControlCallbackContext) );

	ctl_callback_ctx->event_name = event_name ;
	ctl_callback_ctx->funcp = new_funcp ;
	ctl_callback_ctx->rt = rt ;
	ctl_callback_ctx->guiwindow_obj = new_guiwindow_obj ;
	ctl_callback_ctx->guictl_obj = new_guictl_obj ;
	list_add_tail( & (ctl_callback_ctx->ctl_callback_ctx_list_node) , & (guiwindow_obj_direct_prop->ctl_gene_callback_ctx_list) );

	if( guiwindow_obj_direct_prop->is_showed == TRUE )
	{
		g_signal_connect( GetControlGtkEventBoxOrInnerOrWidget(guictl_common) , ctl_callback_ctx->event_name , G_CALLBACK(OnGtkControlGeneralEventProc) , ctl_callback_ctx );
	}

	return 0;
}

void OnGtkControlGeneralEventProc( GtkWidget *widget , gpointer data )
{
	struct ControlCallbackContext			*ctl_callback_ctx = (struct ControlCallbackContext *)data ;
	struct ZlangDirectProperty_guiwindow		*guiwindow_direct_prop = GetObjectDirectProperty(ctl_callback_ctx->guiwindow_obj) ;
	struct ZlangDirectProperty_guiwidget_common	*guiwindow_common = (struct ZlangDirectProperty_guiwidget_common *)guiwindow_direct_prop ;

	if( ! gtk_widget_is_visible(guiwindow_common->gtk_widget) )
		return;

	InvokeGtkControlGeneralEventCallbackFunction( ctl_callback_ctx );

	return;
}

int InvokeGtkControlGeneralEventCallbackFunction( struct ControlCallbackContext *ctl_callback_ctx )
{
	struct ZlangRuntime		*rt = ctl_callback_ctx->rt ;
	struct ZlangObject		*guiwindow_obj = ctl_callback_ctx->guiwindow_obj ;
	struct ZlangObject		*guictl_obj = ctl_callback_ctx->guictl_obj ;
	char				*event_name = ctl_callback_ctx->event_name ;
	struct ZlangObject		*in_obj = NULL ;
	struct ZlangFunction		*func = NULL ;

	struct ZlangObject		*obj = NULL ;
	struct ZlangObjectsStackFrame	*curr_objs_stack_frame = NULL ;
	struct ZlangFunctionParameter	*func_param_output = NULL ;
	struct ZlangFunctionParameter	*func_param_guiwindow = NULL ;
	struct ZlangFunctionParameter	*func_param_guictl = NULL ;
	struct ZlangFunctionParameter	*func_param_guievent = NULL ;

	int				nret = 0 ;

	CallRuntimeFunction_functionptr_GetObjectPtr( rt , ctl_callback_ctx->funcp , & in_obj );
	CallRuntimeFunction_functionptr_GetFunctionPtr( rt , ctl_callback_ctx->funcp , & func );

	func_param_output = GetFunctionOutParameter( func ) ;
	if( func_param_output == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] output params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_output) , != , "void" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] output param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guiwindow = TravelFunctionInputParameter( rt , func , NULL ) ;
	if( func_param_guiwindow == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guiwindow) , != , "guiwindow" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guictl = TravelFunctionInputParameter( rt , func , func_param_guiwindow ) ;
	if( func_param_guictl == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guictl) , != , GetCloneObjectName(guictl_obj) ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guievent = TravelFunctionInputParameter( rt , func , func_param_guictl ) ;
	if( func_param_guievent == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guievent) , != , "string" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	IncreaseStackFrame( rt , GetFunctionName(func) ) ;
	curr_objs_stack_frame = GetCurrentLocalObjectsStackFrame( rt ) ;

	obj = ReferObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guiwindow) , guiwindow_obj ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}

	obj = ReferObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guictl) , guictl_obj ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}

	obj = CloneStringObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guievent) ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneStringObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}
	nret = CallRuntimeFunction_string_SetStringValue( rt , obj , event_name , STRLEN_OF_STRING ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_string_SetStringValue failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_SET_STRING_VALUE_FAILED );
	}

	MarkInputParamtersTop( curr_objs_stack_frame );

	MarkOutputParamtersTop( curr_objs_stack_frame );

	nret = InvokeEntryFunction( rt , in_obj , func ) ;
	DecreaseStackFrame( rt );
	if( nret )
	{
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_INVOKE_ENTRY_FUNCTION_FAILED );
	}

	return 0;
}

int AddControlFocusEventCallback( struct ZlangRuntime *rt , struct ZlangObject *guiwindow_obj , struct ZlangObject *guictl_obj , char *event_name , struct ZlangObject *funcp )
{
	void						*guictl_obj_direct_prop = GetObjectDirectProperty(guictl_obj) ;
	struct ZlangDirectProperty_guiwidget_common	*guictl_common = (struct ZlangDirectProperty_guiwidget_common *)guictl_obj_direct_prop ;
	struct ZlangDirectProperty_guiwindow		*guiwindow_obj_direct_prop = GetObjectDirectProperty(guiwindow_obj) ;
	struct ZlangObject				*new_funcp = NULL ;
	struct ZlangObject				*new_guiwindow_obj = NULL ;
	struct ZlangObject				*new_guictl_obj = NULL ;
	struct ControlCallbackContext			*ctl_callback_ctx = NULL ;

	new_funcp = TransferInputObjectToNewObject( rt , funcp ) ;
	if( new_funcp == NULL )
		return GetRuntimeErrorNo(rt);

	new_guiwindow_obj = TransferInputObjectToNewObject( rt , guiwindow_obj ) ;
	if( new_guiwindow_obj == NULL )
		return GetRuntimeErrorNo(rt);

	new_guictl_obj = TransferInputObjectToNewObject( rt , guictl_obj ) ;
	if( new_guictl_obj == NULL )
		return GetRuntimeErrorNo(rt);

	ctl_callback_ctx = malloc( sizeof(struct ControlCallbackContext) ) ;
	if( ctl_callback_ctx == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc failed" )
		return ThrowErrorException( rt , ZLANG_ERROR_ALLOC , EXCEPTION_MESSAGE_ALLOC_FAILED );
	}
	memset( ctl_callback_ctx , 0x00 , sizeof(struct ControlCallbackContext) );

	ctl_callback_ctx->event_name = event_name ;
	ctl_callback_ctx->funcp = new_funcp ;
	ctl_callback_ctx->rt = rt ;
	ctl_callback_ctx->guiwindow_obj = new_guiwindow_obj ;
	ctl_callback_ctx->guictl_obj = new_guictl_obj ;
	list_add_tail( & (ctl_callback_ctx->ctl_callback_ctx_list_node) , & (guiwindow_obj_direct_prop->ctl_focus_callback_ctx_list) );

	if( guiwindow_obj_direct_prop->is_showed == TRUE )
	{
		GtkEventController *controller = gtk_event_controller_focus_new() ;
		g_signal_connect( controller , ctl_callback_ctx->event_name , G_CALLBACK(OnGtkControlFocusEventProc) , ctl_callback_ctx );
		gtk_widget_add_controller( guictl_common->gtk_widget , controller );
	}

	return 0;
}

int AddControlUnfocusEventCallback( struct ZlangRuntime *rt , struct ZlangObject *guiwindow_obj , struct ZlangObject *guictl_obj , char *event_name , struct ZlangObject *funcp )
{
	void						*guictl_obj_direct_prop = GetObjectDirectProperty(guictl_obj) ;
	struct ZlangDirectProperty_guiwidget_common	*guictl_common = (struct ZlangDirectProperty_guiwidget_common *)guictl_obj_direct_prop ;
	struct ZlangDirectProperty_guiwindow		*guiwindow_obj_direct_prop = GetObjectDirectProperty(guiwindow_obj) ;
	struct ZlangObject				*new_funcp = NULL ;
	struct ZlangObject				*new_guiwindow_obj = NULL ;
	struct ZlangObject				*new_guictl_obj = NULL ;
	struct ControlCallbackContext			*ctl_callback_ctx = NULL ;

	new_funcp = TransferInputObjectToNewObject( rt , funcp ) ;
	if( new_funcp == NULL )
		return GetRuntimeErrorNo(rt);

	new_guiwindow_obj = TransferInputObjectToNewObject( rt , guiwindow_obj ) ;
	if( new_guiwindow_obj == NULL )
		return GetRuntimeErrorNo(rt);

	new_guictl_obj = TransferInputObjectToNewObject( rt , guictl_obj ) ;
	if( new_guictl_obj == NULL )
		return GetRuntimeErrorNo(rt);

	ctl_callback_ctx = malloc( sizeof(struct ControlCallbackContext) ) ;
	if( ctl_callback_ctx == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc failed" )
		return ThrowErrorException( rt , ZLANG_ERROR_ALLOC , EXCEPTION_MESSAGE_ALLOC_FAILED );
	}
	memset( ctl_callback_ctx , 0x00 , sizeof(struct ControlCallbackContext) );

	ctl_callback_ctx->event_name = event_name ;
	ctl_callback_ctx->funcp = new_funcp ;
	ctl_callback_ctx->rt = rt ;
	ctl_callback_ctx->guiwindow_obj = new_guiwindow_obj ;
	ctl_callback_ctx->guictl_obj = new_guictl_obj ;
	list_add_tail( & (ctl_callback_ctx->ctl_callback_ctx_list_node) , & (guiwindow_obj_direct_prop->ctl_unfocus_callback_ctx_list) );

	if( guiwindow_obj_direct_prop->is_showed == TRUE )
	{
		GtkEventController *controller = gtk_event_controller_focus_new() ;
		g_signal_connect( controller , ctl_callback_ctx->event_name , G_CALLBACK(OnGtkControlFocusEventProc) , ctl_callback_ctx );
		gtk_widget_add_controller( guictl_common->gtk_widget , controller );
	}

	return 0;
}

void OnGtkControlFocusEventProc( GtkWidget *widget , gpointer data )
{
	struct ControlCallbackContext	*ctl_callback_ctx = (struct ControlCallbackContext *)data ;

	InvokeGtkControlGeneralEventCallbackFunction( ctl_callback_ctx );

	return;
}

void OnGtkControlUnfocusEventProc( GtkWidget *widget , gpointer data )
{
	struct ControlCallbackContext	*ctl_callback_ctx = (struct ControlCallbackContext *)data ;

	InvokeGtkControlGeneralEventCallbackFunction( ctl_callback_ctx );

	return;
}

int AddControlKeyEventCallback( struct ZlangRuntime *rt , struct ZlangObject *guiwindow_obj , struct ZlangObject *guictl_obj , char *event_name , struct ZlangObject *funcp )
{
	struct ZlangDirectProperty_guiwindow		*guiwindow_obj_direct_prop = GetObjectDirectProperty(guiwindow_obj) ;
	struct ZlangDirectProperty_guiwidget_common	*guiwindow_common = (struct ZlangDirectProperty_guiwidget_common *)guiwindow_obj_direct_prop ;
	struct ZlangObject				*new_funcp = NULL ;
	struct ZlangObject				*new_guiwindow_obj = NULL ;
	struct ZlangObject				*new_guictl_obj = NULL ;
	struct ControlCallbackContext			*ctl_callback_ctx = NULL ;
	
	new_funcp = TransferInputObjectToNewObject( rt , funcp ) ;
	if( new_funcp == NULL )
		return GetRuntimeErrorNo(rt);

	new_guiwindow_obj = TransferInputObjectToNewObject( rt , guiwindow_obj ) ;
	if( new_guiwindow_obj == NULL )
		return GetRuntimeErrorNo(rt);

	new_guictl_obj = TransferInputObjectToNewObject( rt , guictl_obj ) ;
	if( new_guictl_obj == NULL )
		return GetRuntimeErrorNo(rt);

	ctl_callback_ctx = malloc( sizeof(struct ControlCallbackContext) ) ;
	if( ctl_callback_ctx == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc failed" )
		return ThrowErrorException( rt , ZLANG_ERROR_ALLOC , EXCEPTION_MESSAGE_ALLOC_FAILED );
	}
	memset( ctl_callback_ctx , 0x00 , sizeof(struct ControlCallbackContext) );
	ctl_callback_ctx->event_name = event_name ;
	ctl_callback_ctx->funcp = new_funcp ;
	ctl_callback_ctx->rt = rt ;
	ctl_callback_ctx->guiwindow_obj = new_guiwindow_obj ;
	ctl_callback_ctx->guictl_obj = new_guictl_obj ;
	list_add_tail( & (ctl_callback_ctx->ctl_callback_ctx_list_node) , & (guiwindow_obj_direct_prop->ctl_key_callback_ctx_list) );

	if( guiwindow_obj_direct_prop->is_showed == TRUE )
	{
		GtkEventController *controller = gtk_event_controller_key_new() ;
		g_signal_connect( controller , ctl_callback_ctx->event_name , G_CALLBACK(OnGtkControlKeyEventProc) , ctl_callback_ctx );
		gtk_widget_add_controller( guiwindow_common->gtk_widget , controller );
	}

	return 0;
}

gboolean OnGtkControlKeyEventProc( GtkWidget *widget , guint keyval , guint keycode , GdkModifierType state , gpointer data )
{
	struct ControlCallbackContext		*ctl_callback_ctx = (struct ControlCallbackContext *)data ;

	ctl_callback_ctx->key_state = state ;
	ctl_callback_ctx->key_val = keyval ;

	InvokeGtkControlKeyEventCallbackFunction( ctl_callback_ctx );
	
	return ctl_callback_ctx->ret_bool;
}

int InvokeGtkControlKeyEventCallbackFunction( struct ControlCallbackContext *ctl_callback_ctx )
{
	struct ZlangRuntime		*rt = ctl_callback_ctx->rt ;
	struct ZlangObject		*guiwindow_obj = ctl_callback_ctx->guiwindow_obj ;
	struct ZlangObject		*guictl_obj = ctl_callback_ctx->guictl_obj ;
	// char				*event_name = ctl_callback_ctx->event_name ;
	struct ZlangObject		*in_obj = NULL ;
	struct ZlangFunction		*func = NULL ;

	struct ZlangObject		*obj = NULL ;
	struct ZlangObjectsStackFrame	*curr_objs_stack_frame = NULL ;
	struct ZlangFunctionParameter	*func_param_output = NULL ;
	struct ZlangFunctionParameter	*func_param_guiwindow = NULL ;
	struct ZlangFunctionParameter	*func_param_guictl = NULL ;
	struct ZlangFunctionParameter	*func_param_key_state = NULL ;
	struct ZlangFunctionParameter	*func_param_key_val = NULL ;

	int				nret = 0 ;

	CallRuntimeFunction_functionptr_GetObjectPtr( rt , ctl_callback_ctx->funcp , & in_obj );
	CallRuntimeFunction_functionptr_GetFunctionPtr( rt , ctl_callback_ctx->funcp , & func );

	func_param_output = GetFunctionOutParameter( func ) ;
	if( func_param_output == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] output params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_output) , != , ZLANG_OBJECT_bool ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] output param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guiwindow = TravelFunctionInputParameter( rt , func , NULL ) ;
	if( func_param_guiwindow == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guiwindow) , != , "guiwindow" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guictl = TravelFunctionInputParameter( rt , func , func_param_guiwindow ) ;
	if( func_param_guictl == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guictl) , != , GetCloneObjectName(guictl_obj) ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_key_state = TravelFunctionInputParameter( rt , func , func_param_guictl ) ;
	if( func_param_key_state == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_key_state) , != , "int" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_key_val = TravelFunctionInputParameter( rt , func , func_param_key_state ) ;
	if( func_param_key_val == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_key_val) , != , "int" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	IncreaseStackFrame( rt , GetFunctionName(func) ) ;
	curr_objs_stack_frame = GetCurrentLocalObjectsStackFrame( rt ) ;

	obj = ReferObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guiwindow) , guiwindow_obj ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}

	obj = ReferObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guictl) , guictl_obj ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}

	obj = CloneIntObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_key_state) ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneIntObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}
	nret = CallRuntimeFunction_int_SetIntValue( rt , obj , ctl_callback_ctx->key_state ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_int_SetIntValue failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_SET_STRING_VALUE_FAILED );
	}

	obj = CloneIntObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_key_val) ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneIntObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}
	nret = CallRuntimeFunction_int_SetIntValue( rt , obj , ctl_callback_ctx->key_val ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_int_SetIntValue failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_SET_STRING_VALUE_FAILED );
	}

	MarkInputParamtersTop( curr_objs_stack_frame );

	obj = CloneBoolObjectInLocalStack( rt , NULL ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneBoolObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}

	MarkOutputParamtersTop( curr_objs_stack_frame );

	nret = InvokeEntryFunction( rt , in_obj , func ) ;
	IsObjectTrueValue( rt , GetOutputParameterInLocalObjectStack(rt,1) , & (ctl_callback_ctx->ret_bool) );
	DecreaseStackFrame( rt );
	if( nret )
	{
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_INVOKE_ENTRY_FUNCTION_FAILED );
	}

	return 0;
}

int AddControlMouseButtonEventCallback( struct ZlangRuntime *rt , struct ZlangObject *guiwindow_obj , struct ZlangObject *guictl_obj , char *event_name , struct ZlangObject *funcp )
{
	void						*guictl_obj_direct_prop = GetObjectDirectProperty(guictl_obj) ;
	struct ZlangDirectProperty_guiwidget_common	*guictl_common = (struct ZlangDirectProperty_guiwidget_common *)guictl_obj_direct_prop ;
	struct ZlangDirectProperty_guiwindow		*guiwindow_obj_direct_prop = GetObjectDirectProperty(guiwindow_obj) ;
	struct ZlangObject				*new_funcp = NULL ;
	struct ZlangObject				*new_guiwindow_obj = NULL ;
	struct ZlangObject				*new_guictl_obj = NULL ;
	struct ControlCallbackContext			*ctl_callback_ctx = NULL ;

	new_funcp = TransferInputObjectToNewObject( rt , funcp ) ;
	if( new_funcp == NULL )
		return GetRuntimeErrorNo(rt);

	new_guiwindow_obj = TransferInputObjectToNewObject( rt , guiwindow_obj ) ;
	if( new_guiwindow_obj == NULL )
		return GetRuntimeErrorNo(rt);

	new_guictl_obj = TransferInputObjectToNewObject( rt , guictl_obj ) ;
	if( new_guictl_obj == NULL )
		return GetRuntimeErrorNo(rt);

	ctl_callback_ctx = malloc( sizeof(struct ControlCallbackContext) ) ;
	if( ctl_callback_ctx == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc failed" )
		return ThrowErrorException( rt , ZLANG_ERROR_ALLOC , EXCEPTION_MESSAGE_ALLOC_FAILED );
	}
	memset( ctl_callback_ctx , 0x00 , sizeof(struct ControlCallbackContext) );

	ctl_callback_ctx->event_name = event_name ;
	ctl_callback_ctx->funcp = new_funcp ;
	ctl_callback_ctx->rt = rt ;
	ctl_callback_ctx->guiwindow_obj = new_guiwindow_obj ;
	ctl_callback_ctx->guictl_obj = new_guictl_obj ;
	list_add_tail( & (ctl_callback_ctx->ctl_callback_ctx_list_node) , & (guiwindow_obj_direct_prop->ctl_mouse_button_callback_ctx_list) );

	if( guiwindow_obj_direct_prop->is_showed == TRUE )
	{
		GtkGesture *gesture = gtk_gesture_click_new();
		gtk_gesture_single_set_button( GTK_GESTURE_SINGLE(gesture) , 0 );
		g_signal_connect( gesture , ctl_callback_ctx->event_name , G_CALLBACK(OnGtkControlMouseButtonEventProc) , ctl_callback_ctx );
		gtk_event_controller_set_propagation_phase( GTK_EVENT_CONTROLLER(gesture) , GTK_PHASE_CAPTURE );
		gtk_widget_add_controller( guictl_common->gtk_widget , GTK_EVENT_CONTROLLER(gesture) );
	}

	return 0;
}

void OnGtkControlMouseButtonEventProc( GtkGestureClick *gesture , int n_press , double x , double y , gpointer data )
{
	struct ControlCallbackContext			*ctl_callback_ctx = (struct ControlCallbackContext *)data ;

	ctl_callback_ctx->button_type = gtk_gesture_single_get_current_button(GTK_GESTURE_SINGLE(gesture)) ;
	ctl_callback_ctx->n_press = n_press ;
	ctl_callback_ctx->x = (int)x ;
	ctl_callback_ctx->y = (int)y ;

	InvokeGtkControlMouseButtonEventCallbackFunction( ctl_callback_ctx );

	return;
}

int InvokeGtkControlMouseButtonEventCallbackFunction( struct ControlCallbackContext *ctl_callback_ctx )
{
	struct ZlangRuntime		*rt = ctl_callback_ctx->rt ;
	struct ZlangObject		*guiwindow_obj = ctl_callback_ctx->guiwindow_obj ;
	struct ZlangObject		*guictl_obj = ctl_callback_ctx->guictl_obj ;
	struct ZlangObject		*in_obj = NULL ;
	struct ZlangFunction		*func = NULL ;

	struct ZlangObject		*obj = NULL ;
	struct ZlangObjectsStackFrame	*curr_objs_stack_frame = NULL ;
	struct ZlangFunctionParameter	*func_param_output = NULL ;
	struct ZlangFunctionParameter	*func_param_guiwindow = NULL ;
	struct ZlangFunctionParameter	*func_param_guictl = NULL ;
	struct ZlangFunctionParameter	*func_param_button_type = NULL ;
	struct ZlangFunctionParameter	*func_param_n_press = NULL ;
	struct ZlangFunctionParameter	*func_param_x = NULL ;
	struct ZlangFunctionParameter	*func_param_y = NULL ;

	int				nret = 0 ;

	CallRuntimeFunction_functionptr_GetObjectPtr( rt , ctl_callback_ctx->funcp , & in_obj );
	CallRuntimeFunction_functionptr_GetFunctionPtr( rt , ctl_callback_ctx->funcp , & func );

	func_param_output = GetFunctionOutParameter( func ) ;
	if( func_param_output == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] output params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_output) , != , "void" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] output param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guiwindow = TravelFunctionInputParameter( rt , func , NULL ) ;
	if( func_param_guiwindow == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guiwindow) , != , "guiwindow" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guictl = TravelFunctionInputParameter( rt , func , func_param_guiwindow ) ;
	if( func_param_guictl == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guictl) , != , GetCloneObjectName(guictl_obj) ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_button_type = TravelFunctionInputParameter( rt , func , func_param_guictl ) ;
	if( func_param_button_type == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_button_type) , != , "int" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_n_press = TravelFunctionInputParameter( rt , func , func_param_button_type ) ;
	if( func_param_n_press == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_n_press) , != , "int" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_x = TravelFunctionInputParameter( rt , func , func_param_n_press ) ;
	if( func_param_x == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_x) , != , "int" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_y = TravelFunctionInputParameter( rt , func , func_param_x ) ;
	if( func_param_y == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_y) , != , "int" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	IncreaseStackFrame( rt , GetFunctionName(func) ) ;
	curr_objs_stack_frame = GetCurrentLocalObjectsStackFrame( rt ) ;

	obj = ReferObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guiwindow) , guiwindow_obj ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}

	obj = ReferObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guictl) , guictl_obj ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}

	obj = CloneIntObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_button_type) ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneIntObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}
	nret = CallRuntimeFunction_int_SetIntValue( rt , obj , ctl_callback_ctx->button_type ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_int_SetIntValue failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_SET_STRING_VALUE_FAILED );
	}

	obj = CloneIntObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_n_press) ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneIntObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}
	nret = CallRuntimeFunction_int_SetIntValue( rt , obj , ctl_callback_ctx->n_press ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_int_SetIntValue failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_SET_STRING_VALUE_FAILED );
	}

	obj = CloneIntObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_x) ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneIntObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}
	nret = CallRuntimeFunction_int_SetIntValue( rt , obj , ctl_callback_ctx->x ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_int_SetIntValue failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_SET_STRING_VALUE_FAILED );
	}

	obj = CloneIntObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_y) ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneIntObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}
	nret = CallRuntimeFunction_int_SetIntValue( rt , obj , ctl_callback_ctx->y ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_int_SetIntValue failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_SET_STRING_VALUE_FAILED );
	}

	MarkInputParamtersTop( curr_objs_stack_frame );

	MarkOutputParamtersTop( curr_objs_stack_frame );

	nret = InvokeEntryFunction( rt , in_obj , func ) ;
	DecreaseStackFrame( rt );
	if( nret )
	{
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_INVOKE_ENTRY_FUNCTION_FAILED );
	}

	return 0;
}

int AddControlNotifyEventCallback( struct ZlangRuntime *rt , struct ZlangObject *guiwindow_obj , struct ZlangObject *guictl_obj , char *event_name , struct ZlangObject *funcp )
{
	void						*guictl_obj_direct_prop = GetObjectDirectProperty(guictl_obj) ;
	struct ZlangDirectProperty_guiwidget_common	*guictl_common = (struct ZlangDirectProperty_guiwidget_common *)guictl_obj_direct_prop ;
	struct ZlangDirectProperty_guiwindow		*guiwindow_obj_direct_prop = GetObjectDirectProperty(guiwindow_obj) ;
	struct ZlangObject				*new_funcp = NULL ;
	struct ZlangObject				*new_guiwindow_obj = NULL ;
	struct ZlangObject				*new_guictl_obj = NULL ;
	struct ControlCallbackContext			*ctl_callback_ctx = NULL ;

	new_funcp = TransferInputObjectToNewObject( rt , funcp ) ;
	if( new_funcp == NULL )
		return GetRuntimeErrorNo(rt);

	new_guiwindow_obj = TransferInputObjectToNewObject( rt , guiwindow_obj ) ;
	if( new_guiwindow_obj == NULL )
		return GetRuntimeErrorNo(rt);

	new_guictl_obj = TransferInputObjectToNewObject( rt , guictl_obj ) ;
	if( new_guictl_obj == NULL )
		return GetRuntimeErrorNo(rt);

	ctl_callback_ctx = malloc( sizeof(struct ControlCallbackContext) ) ;
	if( ctl_callback_ctx == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc failed" )
		return ThrowErrorException( rt , ZLANG_ERROR_ALLOC , EXCEPTION_MESSAGE_ALLOC_FAILED );
	}
	memset( ctl_callback_ctx , 0x00 , sizeof(struct ControlCallbackContext) );

	ctl_callback_ctx->event_name = event_name ;
	ctl_callback_ctx->funcp = new_funcp ;
	ctl_callback_ctx->rt = rt ;
	ctl_callback_ctx->guiwindow_obj = new_guiwindow_obj ;
	ctl_callback_ctx->guictl_obj = new_guictl_obj ;
	list_add_tail( & (ctl_callback_ctx->ctl_callback_ctx_list_node) , & (guiwindow_obj_direct_prop->ctl_notify_callback_ctx_list) );

	if( guiwindow_obj_direct_prop->is_showed == TRUE )
	{
		g_signal_connect( GetControlGtkEventBoxOrInnerOrWidget(guictl_common) , ctl_callback_ctx->event_name , G_CALLBACK(OnGtkControlNotifyEventProc) , ctl_callback_ctx );
	}

	return 0;
}

void OnGtkControlNotifyEventProc( GtkWidget *widget , GParamSpec *pspec , gpointer data )
{
	struct ControlCallbackContext			*ctl_callback_ctx = (struct ControlCallbackContext *)data ;

	InvokeGtkControlNotifyEventCallbackFunction( ctl_callback_ctx );

	return;
}

int InvokeGtkControlNotifyEventCallbackFunction( struct ControlCallbackContext *ctl_callback_ctx )
{
	struct ZlangRuntime		*rt = ctl_callback_ctx->rt ;
	struct ZlangObject		*guiwindow_obj = ctl_callback_ctx->guiwindow_obj ;
	struct ZlangObject		*guictl_obj = ctl_callback_ctx->guictl_obj ;
	char				*event_name = ctl_callback_ctx->event_name ;
	struct ZlangObject		*in_obj = NULL ;
	struct ZlangFunction		*func = NULL ;

	struct ZlangObject		*obj = NULL ;
	struct ZlangObjectsStackFrame	*curr_objs_stack_frame = NULL ;
	struct ZlangFunctionParameter	*func_param_output = NULL ;
	struct ZlangFunctionParameter	*func_param_guiwindow = NULL ;
	struct ZlangFunctionParameter	*func_param_guictl = NULL ;
	struct ZlangFunctionParameter	*func_param_guievent = NULL ;

	int				nret = 0 ;

	CallRuntimeFunction_functionptr_GetObjectPtr( rt , ctl_callback_ctx->funcp , & in_obj );
	CallRuntimeFunction_functionptr_GetFunctionPtr( rt , ctl_callback_ctx->funcp , & func );

	func_param_output = GetFunctionOutParameter( func ) ;
	if( func_param_output == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] output params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_output) , != , "void" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] output param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guiwindow = TravelFunctionInputParameter( rt , func , NULL ) ;
	if( func_param_guiwindow == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guiwindow) , != , "guiwindow" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guictl = TravelFunctionInputParameter( rt , func , func_param_guiwindow ) ;
	if( func_param_guictl == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guictl) , != , GetCloneObjectName(guictl_obj) ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guievent = TravelFunctionInputParameter( rt , func , func_param_guictl ) ;
	if( func_param_guievent == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guievent) , != , "string" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	IncreaseStackFrame( rt , GetFunctionName(func) ) ;
	curr_objs_stack_frame = GetCurrentLocalObjectsStackFrame( rt ) ;

	obj = ReferObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guiwindow) , guiwindow_obj ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}

	obj = ReferObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guictl) , guictl_obj ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}

	obj = CloneStringObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guievent) ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneStringObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}
	nret = CallRuntimeFunction_string_SetStringValue( rt , obj , event_name , STRLEN_OF_STRING ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_string_SetStringValue failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_SET_STRING_VALUE_FAILED );
	}

	MarkInputParamtersTop( curr_objs_stack_frame );

	MarkOutputParamtersTop( curr_objs_stack_frame );

	nret = InvokeEntryFunction( rt , in_obj , func ) ;
	DecreaseStackFrame( rt );
	if( nret )
	{
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_INVOKE_ENTRY_FUNCTION_FAILED );
	}

	return 0;
}

int AddControlListboxRowEventCallback( struct ZlangRuntime *rt , struct ZlangObject *guiwindow_obj , struct ZlangObject *guictl_obj , char *event_name , struct ZlangObject *funcp )
{
	void						*guictl_obj_direct_prop = GetObjectDirectProperty(guictl_obj) ;
	struct ZlangDirectProperty_guiwidget_common	*guictl_common = (struct ZlangDirectProperty_guiwidget_common *)guictl_obj_direct_prop ;
	struct ZlangDirectProperty_guiwindow		*guiwindow_obj_direct_prop = GetObjectDirectProperty(guiwindow_obj) ;
	struct ZlangObject				*new_funcp = NULL ;
	struct ZlangObject				*new_guiwindow_obj = NULL ;
	struct ZlangObject				*new_guictl_obj = NULL ;
	struct ControlCallbackContext			*ctl_callback_ctx = NULL ;

	new_funcp = TransferInputObjectToNewObject( rt , funcp ) ;
	if( new_funcp == NULL )
		return GetRuntimeErrorNo(rt);

	new_guiwindow_obj = TransferInputObjectToNewObject( rt , guiwindow_obj ) ;
	if( new_guiwindow_obj == NULL )
		return GetRuntimeErrorNo(rt);

	new_guictl_obj = TransferInputObjectToNewObject( rt , guictl_obj ) ;
	if( new_guictl_obj == NULL )
		return GetRuntimeErrorNo(rt);

	ctl_callback_ctx = malloc( sizeof(struct ControlCallbackContext) ) ;
	if( ctl_callback_ctx == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc failed" )
		return ThrowErrorException( rt , ZLANG_ERROR_ALLOC , EXCEPTION_MESSAGE_ALLOC_FAILED );
	}
	memset( ctl_callback_ctx , 0x00 , sizeof(struct ControlCallbackContext) );

	ctl_callback_ctx->event_name = event_name ;
	ctl_callback_ctx->funcp = new_funcp ;
	ctl_callback_ctx->rt = rt ;
	ctl_callback_ctx->guiwindow_obj = new_guiwindow_obj ;
	ctl_callback_ctx->guictl_obj = new_guictl_obj ;
	list_add_tail( & (ctl_callback_ctx->ctl_callback_ctx_list_node) , & (guiwindow_obj_direct_prop->ctl_listbox_row_callback_ctx_list) );

	if( guiwindow_obj_direct_prop->is_showed == TRUE )
	{
		g_signal_connect( GetControlGtkEventBoxOrInnerOrWidget(guictl_common) , ctl_callback_ctx->event_name , G_CALLBACK(OnGtkControlListboxRowEventProc) , ctl_callback_ctx );
	}

	return 0;
}

void OnGtkControlListboxRowEventProc( GtkWidget *widget , GtkListBoxRow *row , gpointer data )
{
	struct ControlCallbackContext			*ctl_callback_ctx = (struct ControlCallbackContext *)data ;
	struct ZlangDirectProperty_guiwindow		*guiwindow_direct_prop = GetObjectDirectProperty(ctl_callback_ctx->guiwindow_obj) ;
	struct ZlangDirectProperty_guiwidget_common	*guiwindow_common = (struct ZlangDirectProperty_guiwidget_common *)guiwindow_direct_prop ;

	if( ! gtk_widget_is_visible(guiwindow_common->gtk_widget) )
		return;

	InvokeGtkControlListboxRowEventCallbackFunction( ctl_callback_ctx );

	return;
}

int InvokeGtkControlListboxRowEventCallbackFunction( struct ControlCallbackContext *ctl_callback_ctx )
{
	struct ZlangRuntime		*rt = ctl_callback_ctx->rt ;
	struct ZlangObject		*guiwindow_obj = ctl_callback_ctx->guiwindow_obj ;
	struct ZlangObject		*guictl_obj = ctl_callback_ctx->guictl_obj ;
	char				*event_name = ctl_callback_ctx->event_name ;
	struct ZlangObject		*in_obj = NULL ;
	struct ZlangFunction		*func = NULL ;

	struct ZlangObject		*obj = NULL ;
	struct ZlangObjectsStackFrame	*curr_objs_stack_frame = NULL ;
	struct ZlangFunctionParameter	*func_param_output = NULL ;
	struct ZlangFunctionParameter	*func_param_guiwindow = NULL ;
	struct ZlangFunctionParameter	*func_param_guictl = NULL ;
	struct ZlangFunctionParameter	*func_param_guievent = NULL ;

	int				nret = 0 ;

	CallRuntimeFunction_functionptr_GetObjectPtr( rt , ctl_callback_ctx->funcp , & in_obj );
	CallRuntimeFunction_functionptr_GetFunctionPtr( rt , ctl_callback_ctx->funcp , & func );

	func_param_output = GetFunctionOutParameter( func ) ;
	if( func_param_output == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] output params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_output) , != , "void" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] output param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guiwindow = TravelFunctionInputParameter( rt , func , NULL ) ;
	if( func_param_guiwindow == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guiwindow) , != , "guiwindow" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guictl = TravelFunctionInputParameter( rt , func , func_param_guiwindow ) ;
	if( func_param_guictl == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guictl) , != , GetCloneObjectName(guictl_obj) ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guievent = TravelFunctionInputParameter( rt , func , func_param_guictl ) ;
	if( func_param_guievent == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guievent) , != , "string" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	IncreaseStackFrame( rt , GetFunctionName(func) ) ;
	curr_objs_stack_frame = GetCurrentLocalObjectsStackFrame( rt ) ;

	obj = ReferObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guiwindow) , guiwindow_obj ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}

	obj = ReferObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guictl) , guictl_obj ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}

	obj = CloneStringObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guievent) ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneStringObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}
	nret = CallRuntimeFunction_string_SetStringValue( rt , obj , event_name , STRLEN_OF_STRING ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_string_SetStringValue failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_SET_STRING_VALUE_FAILED );
	}

	MarkInputParamtersTop( curr_objs_stack_frame );

	MarkOutputParamtersTop( curr_objs_stack_frame );

	nret = InvokeEntryFunction( rt , in_obj , func ) ;
	DecreaseStackFrame( rt );
	if( nret )
	{
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_INVOKE_ENTRY_FUNCTION_FAILED );
	}

	return 0;
}

int AddControlFlowboxChildActivatedEventCallback( struct ZlangRuntime *rt , struct ZlangObject *guiwindow_obj , struct ZlangObject *guictl_obj , char *event_name , struct ZlangObject *funcp )
{
	void						*guictl_obj_direct_prop = GetObjectDirectProperty(guictl_obj) ;
	struct ZlangDirectProperty_guiwidget_common	*guictl_common = (struct ZlangDirectProperty_guiwidget_common *)guictl_obj_direct_prop ;
	struct ZlangDirectProperty_guiwindow		*guiwindow_obj_direct_prop = GetObjectDirectProperty(guiwindow_obj) ;
	struct ZlangObject				*new_funcp = NULL ;
	struct ZlangObject				*new_guiwindow_obj = NULL ;
	struct ZlangObject				*new_guictl_obj = NULL ;
	struct ControlCallbackContext			*ctl_callback_ctx = NULL ;

	new_funcp = TransferInputObjectToNewObject( rt , funcp ) ;
	if( new_funcp == NULL )
		return GetRuntimeErrorNo(rt);

	new_guiwindow_obj = TransferInputObjectToNewObject( rt , guiwindow_obj ) ;
	if( new_guiwindow_obj == NULL )
		return GetRuntimeErrorNo(rt);

	new_guictl_obj = TransferInputObjectToNewObject( rt , guictl_obj ) ;
	if( new_guictl_obj == NULL )
		return GetRuntimeErrorNo(rt);

	ctl_callback_ctx = malloc( sizeof(struct ControlCallbackContext) ) ;
	if( ctl_callback_ctx == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc failed" )
		return ThrowErrorException( rt , ZLANG_ERROR_ALLOC , EXCEPTION_MESSAGE_ALLOC_FAILED );
	}
	memset( ctl_callback_ctx , 0x00 , sizeof(struct ControlCallbackContext) );

	ctl_callback_ctx->event_name = event_name ;
	ctl_callback_ctx->funcp = new_funcp ;
	ctl_callback_ctx->rt = rt ;
	ctl_callback_ctx->guiwindow_obj = new_guiwindow_obj ;
	ctl_callback_ctx->guictl_obj = new_guictl_obj ;
	list_add_tail( & (ctl_callback_ctx->ctl_callback_ctx_list_node) , & (guiwindow_obj_direct_prop->ctl_flowbox_child_activated_callback_ctx_list) );

	if( guiwindow_obj_direct_prop->is_showed == TRUE )
	{
		g_signal_connect( GetControlGtkEventBoxOrInnerOrWidget(guictl_common) , ctl_callback_ctx->event_name , G_CALLBACK(OnGtkControlFlowboxChildActivatedEventProc) , ctl_callback_ctx );
	}

	return 0;
}

void OnGtkControlFlowboxChildActivatedEventProc( GtkFlowBox *flow_box , GtkFlowBoxChild *child , gpointer user_data )
{
	struct ControlCallbackContext			*ctl_callback_ctx = (struct ControlCallbackContext *)user_data ;
	struct ZlangDirectProperty_guiflowboxlayout	*guictl_direct_prop = GetObjectDirectProperty(ctl_callback_ctx->guictl_obj) ;

	guictl_direct_prop->child_activated_widget = child ;

	InvokeGtkControlFlowboxChildActivatedEventCallbackFunction( ctl_callback_ctx );

	return;
}

int InvokeGtkControlFlowboxChildActivatedEventCallbackFunction( struct ControlCallbackContext *ctl_callback_ctx )
{
	struct ZlangRuntime		*rt = ctl_callback_ctx->rt ;
	struct ZlangObject		*guiwindow_obj = ctl_callback_ctx->guiwindow_obj ;
	struct ZlangObject		*guictl_obj = ctl_callback_ctx->guictl_obj ;
	char				*event_name = ctl_callback_ctx->event_name ;
	struct ZlangObject		*in_obj = NULL ;
	struct ZlangFunction		*func = NULL ;

	struct ZlangObject		*obj = NULL ;
	struct ZlangObjectsStackFrame	*curr_objs_stack_frame = NULL ;
	struct ZlangFunctionParameter	*func_param_output = NULL ;
	struct ZlangFunctionParameter	*func_param_guiwindow = NULL ;
	struct ZlangFunctionParameter	*func_param_guictl = NULL ;
	struct ZlangFunctionParameter	*func_param_guievent = NULL ;

	int				nret = 0 ;

	CallRuntimeFunction_functionptr_GetObjectPtr( rt , ctl_callback_ctx->funcp , & in_obj );
	CallRuntimeFunction_functionptr_GetFunctionPtr( rt , ctl_callback_ctx->funcp , & func );

	func_param_output = GetFunctionOutParameter( func ) ;
	if( func_param_output == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] output params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_output) , != , "void" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] output param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guiwindow = TravelFunctionInputParameter( rt , func , NULL ) ;
	if( func_param_guiwindow == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guiwindow) , != , "guiwindow" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guictl = TravelFunctionInputParameter( rt , func , func_param_guiwindow ) ;
	if( func_param_guictl == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guictl) , != , GetCloneObjectName(guictl_obj) ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guievent = TravelFunctionInputParameter( rt , func , func_param_guictl ) ;
	if( func_param_guievent == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guievent) , != , "string" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	IncreaseStackFrame( rt , GetFunctionName(func) ) ;
	curr_objs_stack_frame = GetCurrentLocalObjectsStackFrame( rt ) ;

	obj = ReferObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guiwindow) , guiwindow_obj ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}

	obj = ReferObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guictl) , guictl_obj ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}

	obj = CloneStringObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guievent) ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneStringObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}
	nret = CallRuntimeFunction_string_SetStringValue( rt , obj , event_name , STRLEN_OF_STRING ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_string_SetStringValue failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_SET_STRING_VALUE_FAILED );
	}

	MarkInputParamtersTop( curr_objs_stack_frame );

	MarkOutputParamtersTop( curr_objs_stack_frame );

	nret = InvokeEntryFunction( rt , in_obj , func ) ;
	DecreaseStackFrame( rt );
	if( nret )
	{
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_INVOKE_ENTRY_FUNCTION_FAILED );
	}

	return 0;
}

int AddMenuItemEventCallback( struct ZlangRuntime *rt , struct ZlangObject *guiwindow_obj , struct ZlangObject *guictl_obj , char *label , char *event_name , struct ZlangObject *funcp )
{
	struct ZlangDirectProperty_guimenuitem		*guimenuitem_obj_direct_prop = GetObjectDirectProperty(guictl_obj) ;
	struct ZlangDirectProperty_guiwindow		*guiwindow_obj_direct_prop = GetObjectDirectProperty(guiwindow_obj) ;
	struct ZlangObject				*new_funcp = NULL ;
	struct ZlangObject				*new_guiwindow_obj = NULL ;
	struct ZlangObject				*new_guictl_obj = NULL ;
	struct ControlCallbackContext			*ctl_callback_ctx = NULL ;

	new_funcp = TransferInputObjectToNewObject( rt , funcp ) ;
	if( new_funcp == NULL )
		return GetRuntimeErrorNo(rt);

	new_guiwindow_obj = TransferInputObjectToNewObject( rt , guiwindow_obj ) ;
	if( new_guiwindow_obj == NULL )
		return GetRuntimeErrorNo(rt);

	new_guictl_obj = TransferInputObjectToNewObject( rt , guictl_obj ) ;
	if( new_guictl_obj == NULL )
		return GetRuntimeErrorNo(rt);

	ctl_callback_ctx = malloc( sizeof(struct ControlCallbackContext) ) ;
	if( ctl_callback_ctx == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc failed" )
		return ThrowErrorException( rt , ZLANG_ERROR_ALLOC , EXCEPTION_MESSAGE_ALLOC_FAILED );
	}
	memset( ctl_callback_ctx , 0x00 , sizeof(struct ControlCallbackContext) );

	ctl_callback_ctx->event_name = event_name ;
	ctl_callback_ctx->funcp = new_funcp ;
	ctl_callback_ctx->rt = rt ;
	ctl_callback_ctx->guiwindow_obj = new_guiwindow_obj ;
	ctl_callback_ctx->guictl_obj = new_guictl_obj ;
	if( guimenuitem_obj_direct_prop->is_checked == BOOLNULL )
		ctl_callback_ctx->action = g_simple_action_new( label , NULL ) ;
	else
		ctl_callback_ctx->action = g_simple_action_new_stateful( label , NULL , g_variant_new_boolean(guimenuitem_obj_direct_prop->is_checked) ) ;
	list_add_tail( & (ctl_callback_ctx->ctl_callback_ctx_list_node) , & (guiwindow_obj_direct_prop->ctl_menu_item_callback_ctx_list) );

	if( guiwindow_obj_direct_prop->is_showed == TRUE )
	{
		g_signal_connect( ctl_callback_ctx->action , event_name , G_CALLBACK(OnGtkMenuItemEventProc) , ctl_callback_ctx );
		g_action_map_add_action( guiwindow_obj_direct_prop->action_map , G_ACTION(ctl_callback_ctx->action) );
	}

	return 0;
}

void OnGtkMenuItemEventProc( GSimpleAction *action , GVariant *parameter , gpointer data )
{
	struct ControlCallbackContext	*ctl_callback_ctx = (struct ControlCallbackContext *)data ;

	InvokeGtkMenuItemEventCallbackFunction( ctl_callback_ctx );

	return;
}

int InvokeGtkMenuItemEventCallbackFunction( struct ControlCallbackContext *ctl_callback_ctx )
{
	struct ZlangRuntime		*rt = ctl_callback_ctx->rt ;
	struct ZlangObject		*guiwindow_obj = ctl_callback_ctx->guiwindow_obj ;
	struct ZlangObject		*guictl_obj = ctl_callback_ctx->guictl_obj ;
	char				*event_name = ctl_callback_ctx->event_name ;
	struct ZlangObject		*in_obj = NULL ;
	struct ZlangFunction		*func = NULL ;

	struct ZlangObject		*obj = NULL ;
	struct ZlangObjectsStackFrame	*curr_objs_stack_frame = NULL ;
	struct ZlangFunctionParameter	*func_param_guiwindow = NULL ;
	struct ZlangFunctionParameter	*func_param_guictl = NULL ;
	struct ZlangFunctionParameter	*func_param_guievent = NULL ;

	int				nret = 0 ;

	CallRuntimeFunction_functionptr_GetObjectPtr( rt , ctl_callback_ctx->funcp , & in_obj );
	CallRuntimeFunction_functionptr_GetFunctionPtr( rt , ctl_callback_ctx->funcp , & func );

	func_param_guiwindow = TravelFunctionInputParameter( rt , func , NULL ) ;
	if( func_param_guiwindow == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guiwindow) , != , "guiwindow" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guictl = TravelFunctionInputParameter( rt , func , func_param_guiwindow ) ;
	if( func_param_guictl == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guictl) , != , GetCloneObjectName(guictl_obj) ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	func_param_guievent = TravelFunctionInputParameter( rt , func , func_param_guictl ) ;
	if( func_param_guievent == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "func[%s] input params count not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_COUNT_NOT_MATCHED );
	}
	if( STRCMP( GetFunctionParameterParentObjectName(func_param_guievent) , != , "string" ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , "func[%s] input param type not matched" , GetFunctionName(func) )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED , EXCEPTION_MESSAGE_FUNC_PARAMETER_TYPE_NOT_MATCHED );
	}

	IncreaseStackFrame( rt , GetFunctionName(func) ) ;
	curr_objs_stack_frame = GetCurrentLocalObjectsStackFrame( rt ) ;

	obj = ReferObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guiwindow) , guiwindow_obj ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}
	
	obj = ReferObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guictl) , guictl_obj ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}

	obj = CloneStringObjectInLocalStack( rt , GetFunctionParameterObjectName(func_param_guievent) ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneStringObjectInLocalStack failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , GetRuntimeErrorNo(rt) , EXCEPTION_MESSAGE_CLONE_OBJECT_FAILED );
	}
	nret = CallRuntimeFunction_string_SetStringValue( rt , obj , event_name , STRLEN_OF_STRING ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_string_SetStringValue failed[%d]" , nret )
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_SET_STRING_VALUE_FAILED );
	}

	MarkInputParamtersTop( curr_objs_stack_frame );

	MarkOutputParamtersTop( curr_objs_stack_frame );

	nret = InvokeEntryFunction( rt , in_obj , func ) ;
	DecreaseStackFrame( rt );
	if( nret )
	{
		QuitGtkMainLoop( guiwindow_obj );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_INVOKE_ENTRY_FUNCTION_FAILED );
	}

	return 0;
}

#include "charset_GB18030.c"
#include "charset_UTF8.c"

int ZlangImportObjects( struct ZlangRuntime *rt )
{
	struct ZlangObject	*obj = NULL ;
	
	obj = ZlangImportObject_guiwindow( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guifixedlayout( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guiboxlayout( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guicenterboxlayout( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guiflowboxlayout( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guigridlayout( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guiscrollwindowlayout( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guiframelayout( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guipanedlayout( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guinotebooklayout( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guipopoverlayout( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guimenubar( rt ) ;
	if( obj == NULL )
		return 1;

	obj = ZlangImportObject_guimenu( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guimenuitem( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guitoolbar( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guitoolseparatoritem( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guilabel( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guiedit( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guieditarea( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guisourceeditarea( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guibutton( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guispinbutton( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guicheckbutton( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guiradiobutton( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guitogglebutton( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guilinkbutton( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guilistbox( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guicombobox( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guitable( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guitablecolumn_int_text( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guitablecolumn_double_text( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guitablecolumn_string_text( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guitablecolumn_icon( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guitreetable( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guitreenode( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guitreecolumn_toggle( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guitreecolumn_progress( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guitreecolumn_int_text( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guitreecolumn_double_text( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guitreecolumn_string_text( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guilevelbar( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guiprogressbar( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guicalendar( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guiimage( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guiswitch( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guivideo( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guiseparator( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guimessagedialog( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guiaboutdialog( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guicolorchooserdialog( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guifilechooserdialog( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guifontchooserdialog( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guiorientation( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guialign( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guijustify( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guimouse( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guikey( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guilicense( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guimonitor( rt ) ;
	if( obj == NULL )
		return 1;
	
	obj = ZlangImportObject_guiclipboard( rt ) ;
	if( obj == NULL )
		return 1;
	
	ImportCharsetAlias( rt , g_zlang_charset_aliases_GB18030 );
	ImportCharsetAlias( rt , g_zlang_charset_aliases_UTF8 );
	
	return 0;
}

